一些特殊情况的说明

IsEqual

我们都知道IsEqual是这样写的

type IsEqual<A,B> = (A extends B ? true : false) & (B extends A ? true : false);

但是这样判断any类型就有问题

type test = IsEqual<any,true>;//返回的是true

我们改进成这样写

type IsEqual<A,B> = (<T>()=>T extends A ? 1 : 2) extends (<T>()=>T extends B ? 1 : 2) ? true : false;
type test = IsEqual<any,true>;

extends左右类型的位置换一下就报错了

这是我们以前写的,做加法的类型。

type BuildArray<
  Length extends number,
  Ele = unknown,
  Arr extends unknown[] = []
> = Arr['length'] extends Length ?
    Arr :
    BuildArray<Length,Ele,[...Arr,Ele]>
type Add<Num1 extends number, Num2 extends number> = [...BuildArray<Num1>,...BuildArray<Num2>]['length'];
type add = Add<1,2>;

我们将其extends左右类型交换一下

type BuildArray<
  Length extends number,
  Ele = unknown,
  Arr extends unknown[] = []
> = Length extends Arr['length'] ?
    Arr :
    BuildArray<Length,Ele,[...Arr,Ele]>
type Add<Num1 extends number, Num2 extends number> = [...BuildArray<Num1>,...BuildArray<Num2>]['length'];
type add = Add<1,2>;

报错:类型实例化过深,且可能无限。这是为什么呢?我们先来看这串代码

type test = number extends unknown ? true : false;//true
type test2 = unknown extends number ? true : false;//false

如果我们没给Arr[‘length’]指定类型,那么它的类型就是unknown,如果把unknown写在extends左侧,那么可能一直是false,那么就会导致报错。

几个条件类型的特殊情况

联合类型作为类型参数在条件类型左边的时候,会把每个类型单独传入做计算,并把结果合并成联合类型。

type Test<T> = T extends number ? 1 : 2;
type res = Test<1 | 'a'>;//type res = 1 | 2

boolean也是联合类型,是false | true。

type Test<T> = T extends true ? 1 : 2;
type res = Test<boolean>;//type res = false | true

any类型如果在条件类型的左边,则返回trueType和falseType的联合类型。

type Test<T> = T extends true ? 1 : 2;
type res = Test<any>;//type res = 1 | 2

当条件类型的左侧是never的时候直接返回never

type Test<T> = T extends true ? 1 : 2;
type res = Test<never>;//type res = never

参考资料

[1]TypeScript 类型体操通关秘籍