TypeScript 类型速查:通俗理解 + 实战示例
在日常前端开发中,TypeScript 给我们带来的最大好处,就是 类型安全 和 智能提示。
不过,很多同学一看到「交叉类型」「映射类型」这些名词就有点发怵。其实,它们没有那么玄乎,只要搞懂概念 + 使用场景,就能灵活运用到项目里。
本文带你用通俗的语言理解以下几个常见类型:
- 交叉类型(
&) - 联合类型(
|) - 类型别名(
type) - 类型索引(
keyof、索引访问) - 类型约束(
extends) - 映射类型(
{ [K in ...]: ... }) - 条件类型(
T extends U ? X : Y) - 工具类型:
Partial、Readonly、Pick、Record - 泛型
1. 交叉类型(Intersection Types)
👉 概念:把多个类型合并成一个,要求同时满足。
type Person = { name: string }
type Worker = { job: string }
type Employee = Person & Worker
// 等价于 { name: string; job: string }
const x: Employee = { name: "张三", job: "程序员" }
通俗理解:
A 和 B 的交集,既要满足 A,又要满足 B。
在项目里,经常用来「组合多个对象的属性」。
2. 联合类型(Union Types)
👉 概念:一个值可以是几种类型之一。
let id: string | number
id = 123
id = "abc"
通俗理解:
A 或 B,灵活选择一个。
场景:接口的返回值可能是「成功结果」或「错误信息」。
type Success = { code: 200; data: string }
type Fail = { code: 500; error: string }
type Response = Success | Fail
3. 类型别名(Type Aliases)
👉 概念:给复杂的类型起一个名字,方便复用。
type ID = string | number
type User = { id: ID; name: string }
通俗理解:
相当于给复杂的表达式起「变量名」。
比如 string | number 以后直接叫 ID,写代码更清爽。
4. 类型索引(Index Types)
👉 概念:从类型里「取出键」或「取出键的值类型」。
type User = { id: number; name: string; age: number }
type UserKeys = keyof User // "id" | "name" | "age"
type UserName = User["name"] // string
通俗理解:
keyof:取对象的所有 key。T[K]:取某个 key 对应的类型。
在写「通用函数」的时候特别好用。
5. 类型约束(Type Constraints)
👉 概念:通过 extends 限制泛型必须满足某些条件。
function getProp<T extends object, K extends keyof T>(obj: T, key: K) {
return obj[key]
}
const user = { id: 1, name: "张三" }
getProp(user, "name") // ✅ string
// getProp(user, "age") // ❌ 报错
通俗理解:extends 就像给类型加了个「条件过滤器」,不符合就报错。
常用于工具函数里,让输入更安全。
6. 映射类型(Mapped Types)
👉 概念:基于已有类型,批量生成新的类型。
type User = { id: number; name: string }
type PartialUser = {
[K in keyof User]?: User[K]
}
// 等价于 { id?: number; name?: string }
TypeScript 已经内置了很多映射类型,比如:
Partial<T>:把所有属性变成可选Readonly<T>:把所有属性变成只读
通俗理解:
像「for…in」循环那样,把一个类型改造成另一个。
7. 条件类型(Conditional Types)
👉 概念:根据条件返回不同类型。
type IsString<T> = T extends string ? "yes" : "no"
type A = IsString<string> // "yes"
type B = IsString<number> // "no"
通俗理解:
类型里的 if...else。
常见于工具类型,比如提取某些字段:
type ExtractPromise<T> = T extends Promise<infer U> ? U : T
type A = ExtractPromise<Promise<number>> // number
type B = ExtractPromise<string> // string
8. 工具类型
1️⃣ Partial —— 可选属性
通俗理解:把对象类型里所有属性都变成 可选。
- 就像给对象开了“可选开关”,属性可以不用填。
示例:
interface User {
id: number;
name: string;
age: number;
}
type PartialUser = Partial<User>;
const user1: PartialUser = {}; // ✅ 全部可选
const user2: PartialUser = { id: 1 }; // ✅ 可以只写部分属性
用途:
- 用在更新接口,用户可能只改部分字段
- 表单可选项类型定义
2️⃣ Readonly —— 只读属性
通俗理解:把对象类型里所有属性都变成 只读,不能被修改。
- 就像给对象加了锁,属性只能读不能写。
示例:
type ReadonlyUser = Readonly<User>;
const user: ReadonlyUser = { id: 1, name: "Alice", age: 20 };
user.id = 2; // ❌ 报错:无法赋值给 "id"
用途:
- 防止修改配置对象
- Redux/状态管理里的不可变数据
3️⃣ Pick<T, K> —— 挑选属性
通俗理解:从对象类型里 挑出你想要的属性。
- 就像在超市里挑选商品,只留下你需要的几件。
示例:
type UserName = Pick<User, "name" | "id">;
const user: UserName = { id: 1, name: "Alice" }; // ✅
const user2: UserName = { id: 1, age: 20 }; // ❌ 报错:没有 name 属性
用途:
- 做接口返回值限制,只返回部分字段
- 避免传输冗余数据
4️⃣ Record<K, T> —— 生成对象类型
通俗理解:创建一个对象类型,键都是 K,值都是 T。
- 就像给你一个模板,把每个 key 的值类型统一定义好
示例:
type Roles = "admin" | "user" | "guest";
type RoleMap = Record<Roles, string>;
const roleMap: RoleMap = {
admin: "管理员",
user: "普通用户",
guest: "游客"
};
用途:
- 构建字典对象
- 定义配置表、状态映射表
9. 泛型(Generics)
👉 概念:在定义函数、接口或类型时,不直接指定具体类型,而是用一个「占位符」表示类型,调用时再确定。
function identity<T>(value: T): T {
return value
}
const num = identity(123) // 类型推断为 number
const str = identity("hello") // 类型推断为 string
通俗理解:
- 泛型就是「类型的变量」,让代码更灵活复用。
- 就像函数里的参数一样,类型也可以先占位,使用时再确定。
泛型在项目里的高频用法
- 通用函数:
function getFirstItem<T>(arr: T[]): T | undefined {
return arr[0]
}
const firstNum = getFirstItem([1, 2, 3]) // number
const firstStr = getFirstItem(["a", "b"]) // string
- 通用接口 / 类型:
interface ApiResponse<T> {
code: number
data: T
message?: string
}
type UserResponse = ApiResponse<{ id: number; name: string }>
- 配合类型约束:
function getProp<T extends object, K extends keyof T>(obj: T, key: K) {
return obj[key]
}
- 与条件类型结合(高级用法):
type Unpack<T> = T extends Promise<infer U> ? U : T
type A = Unpack<Promise<number>> // number
type B = Unpack<string> // string
一句话记忆法:
- 泛型 = 「类型参数」,先留空,调用时填上
<T>是类型的占位符extends给泛型加条件- 配合条件类型可做高级类型运算
🔗 总结
| 类型 | 符号 | 用途 | |
|---|---|---|---|
| 交叉类型 | & |
合并多个类型 | |
| 联合类型 | ` | ` | 多个类型之一 |
| 类型别名 | type |
给复杂类型起名 | |
| 类型索引 | keyof / T[K] |
获取键或值的类型 | |
| 类型约束 | extends |
限制泛型范围 | |
| 映射类型 | { [K in keyof T]: ... } |
批量生成新类型 | |
| 条件类型 | T extends U ? X : Y |
类型里的 if/else | |
| 工具类型 | Partial / Readonly / Pick / Record |
属性可选/只读/挑选/生成字典映射 |
💡 一句话记忆法:
&是「并且」|是「或者」type是「取个名字」keyof是「拿所有 key」extends是「加个条件」- 映射类型是「for…in」
- 条件类型是「if…else」
- 工具类型 → 快速生成常用类型
- 泛型占位符
更多推荐

所有评论(0)