
为什么高级 TypeScript 类型很重要
TypeScript 的类型系统是图灵完备的——它可以表达你能想象到的几乎任何约束。这里介绍的高级特性让你能够编写既灵活又精确类型的 API,在编译时而非运行时捕获整类错误。

带约束的泛型
// 基本泛型
function identity<T>(value: T): T {
return value;
}
// 带约束的泛型——T 必须具有 length 属性
function longest<T extends { length: number }>(a: T, b: T): T {
return a.length >= b.length ? a : b;
}
longest("hello", "world"); // ✅ 字符串有 .length
longest([1, 2, 3], [1, 2]); // ✅ 数组有 .length
longest(1, 2); // ❌ 错误:数字没有 .length
// 多个类型参数
function zip<T, U>(arr1: T[], arr2: U[]): [T, U][] {
return arr1.map((item, i) => [item, arr2[i]]);
}
const pairs = zip([1, 2, 3], ['a', 'b', 'c']);
// pairs: [number, string][]
条件类型
根据条件分支的类型:
// 基本条件类型
type IsString<T> = T extends string ? 'yes' : 'no';
type A = IsString<string>; // 'yes'
type B = IsString<number>; // 'no'
type C = IsString<string | number>; // 'yes' | 'no'(分发!)
// Extract/Exclude(内置条件类型)
type Exclude<T, U> = T extends U ? never : T;
type Extract<T, U> = T extends U ? T : never;
type Status = 'pending' | 'active' | 'deleted';
type ActiveStatus = Exclude<Status, 'deleted'>; // 'pending' | 'active'
// NonNullable
type NonNullable<T> = T extends null | undefined ? never : T;
type Defined = NonNullable<string | null | undefined>; // string

infer 关键字
从泛型结构中提取类型信息:
// 提取函数返回类型
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
function fetchUser(): Promise<{ id: string; name: string }> { ... }
type UserResponse = ReturnType<typeof fetchUser>;
// UserResponse = Promise<{ id: string; name: string }>
// 解包 Promise
type Awaited<T> = T extends Promise<infer U> ? Awaited<U> : T;
type User = Awaited<Promise<Promise<{ id: string }>>>;
// User = { id: string }
// 提取函数参数类型
type Parameters<T> = T extends (...args: infer P) => any ? P : never;
function createUser(name: string, age: number, role: 'admin' | 'user') {}
type CreateUserParams = Parameters<typeof createUser>;
// [string, number, 'admin' | 'user']
映射类型
系统地转换对象类型:
// 使所有属性可选
type Partial<T> = { [K in keyof T]?: T[K] };
// 使所有属性必填
type Required<T> = { [K in keyof T]-?: T[K] };
// 使所有属性只读
type Readonly<T> = { readonly [K in keyof T]: T[K] };
// 自定义映射:使所有属性可为 null
type Nullable<T> = { [K in keyof T]: T[K] | null };
// 转换值类型
type Stringify<T> = { [K in keyof T]: string };
// 选择键的子集
type Pick<T, K extends keyof T> = { [P in K]: T[P] };
type Omit<T, K extends keyof T> = Pick<T, Exclude<keyof T, K>>;
interface User {
id: string;
name: string;
email: string;
password: string;
}
type PublicUser = Omit<User, 'password'>;
// { id: string; name: string; email: string }
type UserPreview = Pick<User, 'id' | 'name'>;
// { id: string; name: string }

模板字面量类型
在类型层面操作字符串类型:
type EventName = 'click' | 'focus' | 'blur';
type EventHandler = `on${Capitalize<EventName>}`;
// 'onClick' | 'onFocus' | 'onBlur'
// API 路由类型
type HttpMethod = 'get' | 'post' | 'put' | 'delete';
type Endpoint = '/users' | '/orders' | '/products';
type ApiRoute = `${Uppercase<HttpMethod>} ${Endpoint}`;
// 'GET /users' | 'GET /orders' | ...(所有组合)
// 类型安全的 CSS 属性名
type CSSProperty = 'margin' | 'padding' | 'border';
type CSSDirection = 'top' | 'right' | 'bottom' | 'left';
type DirectionalProperty = `${CSSProperty}-${CSSDirection}`;
// 'margin-top' | 'margin-right' | ... 等等
// 对象键推断
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K]
};
interface Config {
host: string;
port: number;
}
type ConfigGetters = Getters<Config>;
// { getHost: () => string; getPort: () => number }
可辨识联合
对类型安全的变体进行模式匹配:
type Result<T, E = Error> =
| { success: true; data: T }
| { success: false; error: E };
async function fetchUser(id: string): Promise<Result<User>> {
try {
const user = await db.users.findById(id);
return { success: true, data: user };
} catch (error) {
return { success: false, error: error as Error };
}
}
const result = await fetchUser('123');
if (result.success) {
console.log(result.data.name); // TypeScript 知道 data 存在
} else {
console.error(result.error.message); // TypeScript 知道 error 存在
}
// 穷举匹配
type Shape =
| { kind: 'circle'; radius: number }
| { kind: 'square'; side: number }
| { kind: 'triangle'; base: number; height: number };
function area(shape: Shape): number {
switch (shape.kind) {
case 'circle': return Math.PI * shape.radius ** 2;
case 'square': return shape.side ** 2;
case 'triangle': return 0.5 * shape.base * shape.height;
default:
// 如果你添加了新的 Shape 变体而未处理,此行会报错
const _exhaustive: never = shape;
throw new Error(`Unhandled: ${_exhaustive}`);
}
}
工具类型模式
// 深度可选(递归地使所有属性可选)
type DeepPartial<T> = {
[K in keyof T]?: T[K] extends object ? DeepPartial<T[K]> : T[K];
};
// 递归只读
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object ? DeepReadonly<T[K]> : T[K];
};
// 将联合类型展平为交叉类型
type UnionToIntersection<U> =
(U extends any ? (x: U) => void : never) extends (x: infer I) => void
? I
: never;
// 使特定键必填,其余可选
type RequiredKeys<T, K extends keyof T> = Omit<T, K> & Required<Pick<T, K>>;
interface CreateUserDto {
name?: string;
email?: string;
role?: string;
}
type ValidCreateUserDto = RequiredKeys<CreateUserDto, 'name' | 'email'>;
// { name: string; email: string; role?: string }
→ 使用 JSON Viewer 查看和检查复杂的 TypeScript 数据结构。