CodeWalk

TypeScript Exclude/Extract/NonNullable 联合类型操作工具

作者:屠龙少年 · 2026-05-30 12:55

请解释 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

应用场景

  • ExcludeOmit<T, K> 实现基础 → Pick<T, Exclude<keyof T, K>>
  • Extract:从联合类型中提取特定类型
  • NonNullable:API 响应类型去空、表单值去 null

注意:如果 T 不是裸类型参数(如 T[]),不会分布式分发。用 [T] extends [U] 可改为非分布式判断。