TypeScript 映射类型与条件类型
映射类型与条件类型是 TypeScript 高阶类型体系的核心,下面梳理用法与原理。
映射类型
使用 in 遍历联合类型生成新对象类型:
TypeScript
type Options = {
[K in "host" | "port" | "timeout"]: string;
};
// 等价于:{ host: string; port: string; timeout: string; }
基于现有类型映射
TypeScript
interface User {
name: string;
age: number;
email: string;
}
type UserOptions = {
[K in keyof User]: User[K];
};
// 等价于 User
修饰符
TypeScript
// 添加可选
type Partial<T> = {
[K in keyof T]?: T[K];
};
// 添加只读
type Readonly<T> = {
readonly [K in keyof T]: T[K];
};
// 移除可选(-?)
type Required<T> = {
[K in keyof T]-?: T[K];
};
// 移除只读(-readonly)
type Mutable<T> = {
-readonly [K in keyof T]: T[K];
};
键名重映射
TypeScript
type Getters<T> = {
[K in keyof T as `get${Capitalize<string & K>}`]: () => T[K];
};
interface Person { name: string; age: number; }
type LazyPerson = Getters<Person>;
// { getName(): string; getAge(): number; }
过滤键名
TypeScript
type ExcludeMethods<T> = {
[K in keyof T as T[K] extends Function ? never : K]: T[K];
};
class User {
id: string = "";
getName() { return "Alice"; }
}
type DataOnly = ExcludeMethods<User>;
// { id: string }
条件类型
语法 T extends U ? X : Y:
TypeScript
type IsString<T> = T extends string ? true : false;
type A = IsString<string>; // true
type B = IsString<number>; // false
infer 类型推断
TypeScript
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : any;
function getUser() { return { id: 1, name: "Alice" }; }
type User = ReturnType<typeof getUser>;
// { id: number; name: string; }
条件类型链
TypeScript
type Flatten<T> = T extends string[]
? T[number]
: T extends infer U[]
? U
: T;
type A = Flatten<string[]>; // string
type B = Flatten<number[]>; // number
type C = Flatten<boolean>; // boolean
分布式条件类型
联合类型传入条件类型时自动分发处理:
TypeScript
type ToArray<T> = T extends any ? T[] : never;
type A = ToArray<string | number>;
// 分发为:ToArray<string> | ToArray<number>
// 结果:string[] | number[]
阻止分发
用元组包裹类型参数:
TypeScript
type ToArrayNonDist<T> = [T] extends [any] ? T[] : never;
type B = ToArrayNonDist<string | number>;
// [string | number] extends [any] 不触发分发
// 结果:(string | number)[]
分布式排除
TypeScript
type RemoveNull<T> = T extends null ? never : T;
type A = RemoveNull<string | number | null>;
// 分发为:RemoveNull<string> | RemoveNull<number> | RemoveNull<null>
// 结果:string | number
NonNullable 内置实现
TypeScript
// TypeScript 内置
type NonNullable<T> = T extends null | undefined ? never : T;
type A = NonNullable<string | null | undefined>;
// string
要点总结
- 映射类型
[K in keyof T]遍历对象键生成新类型 - 修饰符
?/readonly添加可选/只读,-?/-readonly移除 - 键名重映射
as语法转换键名格式 - 条件类型
T extends U ? X : Y实现类型分支 infer在条件类型中推断并提取类型- 联合类型传入条件类型时自动分发,用元组
[T]阻止分发
📝 发现内容有误?点击此处直接编辑