[TypeScript] Type Challenges #43 - Exclude

81 阅读1分钟

题目描述

实现内置的Exclude<T, U>类型,但不能直接使用它本身。

从联合类型 T 中排除 U 中的类型,来构造一个新的类型。

例如:

type Result = MyExclude<'a' | 'b' | 'c''a'// 'b' | 'c'

题解

// ============= Test Cases =============
import type { EqualExpect } from './test-utils'

type cases = [
  Expect<Equal<MyExclude<'a' | 'b' | 'c''a'>, 'b' | 'c'>>,
  Expect<Equal<MyExclude<'a' | 'b' | 'c''a' | 'b'>, 'c'>>,
  Expect<Equal<MyExclude<string | number | (() => void), Function>, string | number>>,
]


// ============= Your Code Here =============
type MyExclude<T, U> = T extends U ? never : T;

1、TypeScript 处理联合类型的条件判断时,会依次对每一个成员进行单独的判断

例如,MyExclude<'a' | 'b' | 'c', 'a'>,也就是分别判断'a' extends 'a''b' extends 'a''c' extends 'a'

'a' extends 'a'成立,返回never

'b' extends 'a'不成立,返回'b'

'c' extends 'a'不成立,返回'c'

最后再把每个结果合并起来,形成最终的返回类型。在 TypeScript 中,当联合类型中出现never时,由于never表示不存在的值,所以在合并联合类型的过程中,never会被自动忽略或者说舍弃掉。所以最终合并的结果是'b' | 'c'