TypeScript Exclude/Extract/NonNullable 联合类型操作工具
请解释 TypeScript 中 Exclude、Extract、NonNullable 三个操作联合类型的工具类型原理与使用场景。
回答
屠龙少年
三个工具类型都利用分布式条件类型:当条件类型作用于联合类型的裸类型参数时,会分别对每个成员应用条件。
Exclude<T, U>:从联合类型 T 中排除可赋值给 U 的类型
type MyExclude<T, U> = T extends U ? never : T;
// 使用分布式:type T = 'a' | 'b' | 'c'
// 'a' extends 'a' ? never : 'a' → never
// 'b' extends 'a' ? never : 'b' → 'b'
// 'c' extends 'a' ? never : 'c' → 'c'
// 结果:'b' | 'c'
type T = Exclude<'a' | 'b' | 'c', 'a'>; // 'b' | 'c'
type T2 = Exclude<string | number | (() => void), Function>; // string | number
Extract<T, U>:从联合类型 T 中提取可赋值给 U 的类型
type MyExtract<T, U> = T extends U ? T : never;
type E = Extract<'a' | 'b' | 'c', 'a' | 'b'>; // 'a' | 'b'
NonNullable:从联合类型中排除 null 和 undefined
type MyNonNullable<T> = T extends null | undefined ? never : T;
type N = NonNullable<string | number | null | undefined>; // string | number
应用场景:
- Exclude:
Omit<T, K>实现基础 →Pick<T, Exclude<keyof T, K>> - Extract:从联合类型中提取特定类型
- NonNullable:API 响应类型去空、表单值去 null
注意:如果 T 不是裸类型参数(如 T[]),不会分布式分发。用 [T] extends [U] 可改为非分布式判断。