匹配模式做提取

数组类型

提取数组的第一个元素的类型

type GetFirst<Arr extends unknown[]> = Arr extends [infer First, ...unknown[]] ? First : never;
type arr = GetFirst<[1,2,3]>;

提取数组的最后一个元素的类型

type GetLast<Arr extends unknown[]> = Arr extends [...unknown[], infer Last] ? Last : never;
type arr = GetLast<[1,2,3]>;

去掉数组最后一个元素的类型

type PopArr<Arr extends unknown[]> = Arr extends [] ? [] : Arr extends [...infer Rest, unknown] ? Rest : never;
type arr = PopArr<[1,2,3]>;

去掉数组第一个元素的类型

type ShiftArr<Arr extends unknown[]> = Arr extends [] ? [] : Arr extends [unknown, ...infer Rest] ? Rest : never;
type arr = ShiftArr<[1,2,3]>;

字符串类型

判断字符串是否以某个前缀开始

type StartsWith<Str extends string,Prefix extends string> = Str extends `${Prefix}${string}` ? true : false;
type str = StartsWith<'111 222','111'>;
type str2 = StartsWith<'111 222','222'>;

字符串替换

type ReplaceStr<
  Str extends string,
  From extends string,
  To extends string
> = Str extends `${infer Prefix}${From}${infer Suffix}` ?
    `${Prefix}${To}${Suffix}` : Str
type str = ReplaceStr<'111 2 333','2','4'>;

递归去除字符串中的右侧空格

type TrimStringRight<Str extends string> = 
Str extends `${infer Rest}${' '|'\n'|'\t'}` ?
TrimStringRight<Rest> : Str;
type str = TrimStringRight<'   111   '>;

递归去除字符串中的左侧空格

type TrimStringLeft<Str extends string> = 
Str extends `${' '|'\n'|'\t'}${infer Rest}` ?
TrimStringLeft<Rest> : Str;
type str = TrimStringLeft<'   111   '>;

递归去除字符串中的左右侧空格

type TrimStr<Str extends string> = TrimStringRight<TrimStringLeft<Str>>;
type str = TrimStr<'   1 1 1   '>;

函数

提取参数的类型

type GetParameters<Func extends Function> = Func extends (...args:infer Args)=>unknown ? Args : never;
type func = GetParameters<(a:string)=>void>;

提取返回值

type GetReturnType<Func extends Function> = Func extends (...args:any[])=>infer ReturnType ? ReturnType : never;
type func = GetReturnType<(a:string)=>void>;

提取函数中的this

因为如果我们new一个实例,那么它的this是不会变动的,我们使用call等函数改变this指向是错误的,所以我们要写一个改变this就报错的匹配模式。

type GetThisParameterType<T> = T extends (this:infer ThisType, ...args:unknown[])=>unknown ? ThisType : never;
class Dong {
  name: string;
  constructor() {
      this.name = "dong";
  }
  hello(this: Dong) {
      return 'hello, I\'m ' + this.name;
  }
}
const dong = new Dong();
type func = GetThisParameterType<typeof dong.hello>;

构造器

匹配提取出实例对象

interface Person{
  name: string
}
interface PersonConstructor{
  new(name:string):Person
}
type GetInstanceType<ConstructorType extends new(...arg:any)=>any> = 
ConstructorType extends new(...args:any)=>infer InstanceType ? InstanceType : never;
type person = GetInstanceType<PersonConstructor>;

提取构造器的参数

interface Person{
  name: string
}
interface PersonConstructor{
  new(name:string):Person
}
type GetConstructorParameters<ConstructorType extends new(...args:any)=>any> = 
ConstructorType extends new(...args:infer ParametersType)=>any ? ParametersType : never;
type person = GetConstructorParameters<PersonConstructor>;

索引类型

提取ref的值的类型

type GetRefProps<Props> = 'ref' extends keyof Props ?
  Props extends {ref?:infer Value|undefined} ? Value : never
: never
type ref = GetRefProps<{ref: '1'}>;

参考资料

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