高级类型
条件类型与 infer
理解条件类型语法、infer 关键字提取类型
条件类型与 infer
条件类型是 TypeScript 类型系统的"if-else",infer 则能从中提取类型。
学完本章你将: 掌握条件类型语法、infer、分布式条件类型。
条件类型语法
typescript
// 基本语法:T extends U ? X : Y
type IsArray<T> = T extends unknown[] ? true : false;
type A = IsArray<string[]>; // true
type B = IsArray<number>; // false
// 嵌套条件
type TypeName<T> =
T extends string ? "string" :
T extends number ? "number" :
T extends boolean ? "boolean" :
T extends Function ? "function" :
"object";
分布式条件类型
typescript
// 当 T 是联合类型时,条件类型分布到每个成员
type ToArray<T> = T extends unknown ? T[] : never;
// 注意:分布式
type R1 = ToArray<string | number>; // string[] | number[]
// 等价于:ToArray<string> | ToArray<number>
// 阻止分布式:用元组包裹
type ToArrayNonDist<T> = [T] extends [unknown] ? T[] : never;
type R2 = ToArrayNonDist<string | number>; // (string | number)[]
infer 提取
typescript
// 提取数组元素
type Flatten<T> = T extends (infer Item)[] ? Item : T;
type F1 = Flatten<string[]>; // string
type F2 = Flatten<number>; // number
// 提取 Promise 值
type Unwrap<T> = T extends Promise<infer V> ? Unwrap<V> : T;
type U1 = Unwrap<Promise<Promise<number>>>; // number(递归)
// 提取函数参数第一个
type FirstArg<T> = T extends (first: infer F, ...rest: infer _) => unknown ? F : never;
type FA = FirstArg<(a: string, b: number) => void>; // string
实战:深度 Readonly
typescript
type DeepReadonly<T> = {
readonly [K in keyof T]: T[K] extends object
? T[K] extends Function
? T[K]
: DeepReadonly<T[K]>
: T[K];
};
interface Config {
server: { host: string; port: number };
timeout: number;
}
type ReadonlyConfig = DeepReadonly<Config>;
// { readonly server: { readonly host: string; readonly port: number }; readonly timeout: number }