模式匹配
字符串可以与正则做模式匹配,找到匹配的部分提取子组,之后可以用 $1, $2 … 这种方式引用匹配的子组
'abc'.replace(/a(b)c/, '$1$1$1'); // 'b,b,b'
Typescript 的类型也可以做模式匹配
比如一个 Promise 类型,相提取 value 的类型:
type p = Promise<'xxxx'>;
type GetValueType<P> = P extends Promise<infer Value> ? Value : never;
通过 extends 对传入的类型参数 P 做模式匹配,其中值的类型是需要提取。
通过 infer 声明一个局部的变量 Value 来保存,如果匹配就返回匹配到的 Value,否则返回 never 代表没有匹配到。
Typescript 类型的模式匹配是通过 extends 对类型参数做匹配,结果保存到通过 infer 声明的局部类型变量里,如果匹配就能从该局部变量里拿到提取出的类型。
数组类型的模式匹配
type arr = [1, 2, 3];
// First [1, 2, 3] -> 1
type GetFirst<Arr extends unknown[]> =
Arr extends [infer First, ...unknown[]] ? First : never;
// Last [1, 2, 3] -> 3
type GetLast<Arr extends unknown[]> =
Arr extends [...unknown[], infer Last] ? Last : never;
// PopArr [1, 2, 3] -> [1, 2]
type PopArr<Arr extends unknown[]> =
Arr extends [] ? []
: Arr extends [...infer Rest, unknown] ? Rest : never;
// ShiftArr [1, 2, 3] -> [2, 3]
type ShiftArr<Arr extends unknown[]> =
Arr extends [] ? []
: Arr extends [unknown, ...infer Rest] ? Rest : never;
字符串类型的模式匹配
// StartsWith
type StartsWith<Str extends string, Prefix extends string> =
Str extends `${Prefix}${string}` ? true : false;
// Replace
type ReplaceStr<
Str extends string,
From extends string,
To extends string
> = Str extends `${infer Prefix}${From}${infer Suffix}`
? `${Prefix}${To}${Suffix}` : Str;
// TrimRight
type TrimRight<Str extends string> =
Str extends `${infer Rest}${' ' | '\n' | '\t'}`
? TrimRight<Rest> : Str;
// TrimLeft
type TrimLeft<Str extends string> =
Str extends `${' ' | '\n' | '\t'}${infer Rest}`
? TrimLeft<Rest> : Str;
// Trim
type Trim<Str extends string> = TrimRight<TrimLeft<Str>>;
函数的模式匹配
// GetParameters
type GetParameters<Func extends Funciton> =
Func extends (...args: infer Args) => unknown ? Args : never;
// GetReturnType
type GetReturnType<Func extends Function> =
Func extends (...args: unknown[]) => infer ReturnType
? ReturnType : never;