Exclude<T, U> 是TypeScript中的一个工具类型,用于从一个类型中减去另一个类型,当需要从联合类型中排除某些值时。
最初在TypeScript中没有方便的方法来从一个类型中减去另一个类型。在创建泛型API或进行重构时,通常需要获取“剩余”类型——除排除值之外的所有值。需要维护多个类似接口,而不是手动处理联合类型。
例如,当有类型'A | B | C'但需要得到没有B的类型时。这在构建复杂函数的输入参数、过滤允许的值和动态生成类型时经常需要。
Exclude解决了这个问题。它的简化签名如下:
type Exclude<T, U> = T extends U ? never : T;
它返回一个类型,排除T中的所有U成员。
示例:
type Status = 'draft' | 'published' | 'removed'; type UserVisibleStatus = Exclude<Status, 'removed'>; const visible: UserVisibleStatus = 'draft'; // OK
关键特性:
可以将Exclude用于普通类型而非联合类型吗?
如果T不是联合类型,但包含在U中——Exclude仍然会起作用,但结果可能是never或T,这并不总是直观的。
Exclude<'a', 'a'> // 结果: never Exclude<'a', 'b'> // 结果: 'a'
Exclude是否删除对象结构中类型的所有引用?
不,Exclude不会递归遍历类型的嵌套字段,只在联合的顶层进行排除。
Exclude如何与接口和对象类型一起工作?
它比较整个类型,而不是单个属性。因此,Exclude从多个接口的联合中删除的只有与U完全相同的类型。
interface A { x: number }; interface B { y: string }; // Exclude<A|B, B> 结果是: A (B完全相同)
通过Exclude<UserRoles, 'admin'>进行用户角色验证,但忘记Exclude不适用于嵌套结构——权限'admin:sub'未被排除。
优点:
缺点:
使用Exclude限制公共API的操作:Exclude<Action, 'delete'>,这排除了危险操作。
优点:
缺点: