TypeScript类型体操挑战(十)

360 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第6天,点击查看活动详情

中等

AnyOf

挑战要求

在线示例

type AnyOf<T extends readonly any[]> = 
  T[number] extends ('' | 0 | false | [] | { [key: string]: never }) 
? false 
: true;

通过索引访问类型可以获取数组中所有元素的联合类型,例如:

type a<T extends readonly any[]> = T[number]
// type b = 3 | 1 | 2
type b = a<[1, 2, 3]>

为了识别出一个空的字面量类型,所以通过声明一个对象类型,并且在里面将值的类型设置为never,也就是:

{ 
  [key: string]: never
}

// 也可以使用内置类型来声明
Record<string, never>

IsNever

挑战要求

在线示例

type IsNever<T> = [T] extends [never] ? true : false;

使用泛型 + 条件判断时,如果传入的值是联合类型,会出现分布,例如:

type IsNever<T> = T extends never ? true : false;
type a = IsNever<never | string>;

// 相当于
type a = never extends never ? true : false | string  extends never ? true : false
  

上面发生分布的时确定的值是never | stringnever是永远不存在的值,它会丢失,为了不让IsNever发生分布的行为,就需要在extends左右两侧的类型上加上[],让它变为一个元组类型,或者直接变成一个数组类型也可以(T[])。

IsUnion

挑战要求

在线示例

type IsUnion<T, B = T> = T extends B ? [B] extends [T] ? false : true : never;

答案参考自解答区,👍比较多的一个,也比较简洁。

刚开始看到这个答案还是有点懵的,然后把每个case都分析了一遍就明白了。里面的知识主要涉及到条件类型

我们通过挑战中的case来看看:

第一种T不是联合类型的。

// case 如下,期望 false
Expect<Equal<IsUnion<string>, false>>
  
// 1.代入到类型中
type IsUnion<string, B = string> = 
  string extends string 
    ? [string] extends [string] 
      ? false 
      : true
  : never;
// 2.string extends string 为 true,进入第二个表达式:
[string] extends [string] ? false : true
// 3.第二步的表达式成立,所以最后返回结果为:true
IsUnion<string> == true

第二种: T为一般的联合类型:

// case 如下,期望 true
Expect<Equal<IsUnion<'a' | 'b'>, true>>

// 1.由于 T 为联合类型,所以会发生分布的行为
'a' extends 'a' | 'b' 
  ? ['a' | 'b'] extends ['a'] 
    ? false 
    : true 
: never
|
'b' extends 'a' | 'b' 
  ? ['a' | 'b'] extends ['b'] 
    ? false 
    : true 
: never;
// 2.执行完第 1 步后的结果为:
true | true
true // 最终就是 true

第三种: T为特殊的联合类型:

// case 如下,期望 false
Expect<Equal<IsUnion<string | never>, false>>
  
// never 是永远不存在的值,在联合类型中,它不是一个有效的值
// 例如下面 T  的类型就是 stirng
type T = string | never;

// 所以上面的 case 可以看做:
Expect<Equal<IsUnion<string | never>, false>> == Expect<Equal<IsUnion<string>, false>>