特殊类型要记清

IsAny

any类型与任何类型的交叉类型都是any,也就是1&any结果是any。

type IsAny<T> = undefined extends (string & T) ? true : false;
type is= IsAny<any>;

其中的stringundefined可以换成别的任意两个不同的类型。

IsEqual

判断两个类型是否相同

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

IsUnion

判断是否是联合类型

type IsUnion<A, B = A> = A extends A ?
  [B] extends [A] ?
    false :
    true
: never;
type is = IsUnion<'1' | 1>;

IsNever

判断是否是never类型。如果条件左边是类型参数,并且传入的是never,那么直接返回never。

type IsNever<T> = T extends number ? 1 : 2;
type is = IsNever<1>;

上面的代码如果判断any会返回1和2的联合类型

type IsNever<T> = T extends number ? 1 : 2;
type is = IsNever<any>;

也可以这样写

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

IsTuple

判断是不是元组元组是数组类型,但是每个元素都是只读的,并且length是数字字面量,而数组的length是number。

type IsTuple<T> = T extends readonly[...args: infer Eles] ?
  NotEqual<Eles['length'],number>
: false;
type NotEqual<A,B> = (<T>()=>T extends A ? 1 : 2) extends (<T>()=>T extends B ? 1 : 2) ? false : true;
type is = IsTuple<number[]>;

联合类型转换成交叉类型

type UnionToIntersection<U> = (U extends U ? (x:U)=>unknown:never) extends (x:infer R)=>unknown ? R : never;
type un = UnionToIntersection<{guang: 1} | {dong: 2}>;

提取索引类型中的可选索引

type GetOptional<Obj extends Record<string,any>> = {
  [Key in keyof Obj as {} extends Pick<Obj, Key> ? Key : never]: Obj[Key]
}
type optional = GetOptional<{
  name?: 1
  age: 2
}>;

提取索引类型中的不可选索引

type isRequired<Obj extends Record<string,any>> = {
  [Key in keyof Obj as {} extends Pick<Obj, Key> ? never : Key]: Obj[Key]
}
type optional = isRequired<{
  name?: 1
  age: 2
}>;

去除索引类型中的索引签名

type Test = {
  [Key: string]: any
}

上面就是索引类型中的索引签名索引类型不能构造成字符串字面量类型,因为它没有名字,而其他索引可以。

type RemoveIndexSignature<Obj extends Record<string,any>> = {
  [Key in keyof Obj as Key extends `${infer Str}` ? Str : never]: Obj[Key];
}
type index = RemoveIndexSignature<{
  name: '1',
  [Key: string]: any
}>;

过滤除class的public属性

keyof只能拿到class的public属性,private和protected的索引会被忽略。

type ClassPublicProps<Obj extends Record<string,any>> = {
  [Key in keyof Obj]: Obj[Key];
}
class Dong {
  public name: string;
  protected age: number;
  private hobbies: string[];
  constructor() {
    this.name = 'dong';
    this.age = 20;
    this.hobbies = ['sleep', 'eat'];
  }
}
type public = ClassPublicProps<Dong>;

as const

用const定义的类型,typescript默认推导出来的类型不是字面量类型。例如:

const obj = {
  name: 1
}
type objType = typeof obj;

我们可以使用as const来处理。

const obj = {
  name: 1
} as const;
type objType = typeof obj;

参考资料

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