递归复用做循环
Promise的递归调用
提取不确定层数的Promise中的value类型的高级类型
type DeepPromiseValueType<P extends Promise<unknown>> =
P extends Promise<infer ValueType> ?
ValueType extends Promise<unknown> ?
DeepPromiseValueType<ValueType>
: ValueType
: never
type promise = DeepPromiseValueType<Promise<Promise<Record<string,any>>>>;
上面的代码可以简化为
type DeepPromiseValueType<T> =
T extends Promise<infer ValueType> ?
DeepPromiseValueType<ValueType>
: T
type promise = DeepPromiseValueType<Promise<Promise<Record<string,any>>>>;
数组类型的递归
确定长度的元组反转
type ReverseArr<Arr extends unknown[]> =
Arr extends [infer One, infer Two, infer Three, infer Four, infer Five] ?
[Five, Four, Three, Two, One]
: never;
type arr = ReverseArr<[1,2,3,4,5]>;
不确定长度的元组反转
type ReverseArr<Arr extends unknown[]> =
Arr extends [infer First, ...infer Rest] ?
[...ReverseArr<Rest>,First]
: Arr;
type arr = ReverseArr<[1,2,3,4,5]>;
寻找元组中是否存在某个元素
type Includes<Arr extends unknown[],FindItem> =
Arr extends [infer First, ...infer Rest] ?
IsEqual<First,FindItem> extends true ? true : Includes<Rest, FindItem>
: false
type IsEqual<A,B> = (A extends B ? true : false) & (B extends A ? true : false);
type arr = Includes<[1,2,3,4],4>;
删除元组中的某个元素
type RemoveItem<
Arr extends unknown[],
Item,
Result extends unknown[] = []
> = Arr extends [infer First, ...infer Rest] ?
IsEqual<First,Item> extends true ? RemoveItem<Rest, Item, Result> : RemoveItem<Rest, Item, [...Result, First]>
: Result;
type IsEqual<A,B> = (A extends B ? true : false) & (B extends A ? true : false);
type arr = RemoveItem<[1,2,3,4,5],4>;
构建一个自定义长度的同一类别的数组
type BuildArray<
Length extends number,
Ele = unknown,
Arr extends unknown[] = []
> = Arr['length'] extends Length ?
Arr :
BuildArray<Length, Ele, [...Arr, Ele]>;
type arr = BuildArray<5,number>;
字符串类型的递归
将字符串中的所用的指定字串替换成另一个字符串
type Replace<
Str extends string,
From extends string,
To extends string,
> = Str extends `${infer Left}${From}${infer Right}` ?
Replace<`${Left}${To}${Right}`,From,To> :
Str;
type str = Replace<'abc abc aaa abc aaa abc ab abc','abc',''>;
将字符串的每个元素提取出来转换成联合类型
例如将"123"
转换成"1" | "2" | "3"
type StringToUnion<Str extends string> = Str extends `${infer Fitsr}${infer Rest}` ?
Fitsr | StringToUnion<Rest> :
never;
type str = StringToUnion<'123'>;
反转字符串类型
type ReverseStr<
Str extends string,
Result extends string = ""
> = Str extends `${infer First}${infer Rest}` ?
ReverseStr<Rest,`${First}${Result}`> :
Result;
type str = ReverseStr<'1234567'>;
对象类型的递归(索引类型的递归)
递归将所有层的索引都变成只读
type DeepReadonly<Obj extends Record<string,any>> = {
readonly [Key in keyof Obj]: Obj[Key] extends Object ?
Obj[Key] extends Function ?
Obj[Key]
: DeepReadonly<Obj[Key]>
: Obj[Key]
}
type obj = DeepReadonly<{
a: {
b: 1
}
}>
如果按照我们的想法,会写出上面的代码,但是如果测试一下我们就会发现,递归没有进行下去。因为ts的类型只有被用到的时候才会被计算。这里只是给第一次的索引加上了只读,但是没有使用。所以不会进行计算,我们可以加一个Obj extends any
让其计算。
type DeepReadonly<Obj extends Record<string,any>> = Obj extends any ?
{
readonly [Key in keyof Obj]: Obj[Key] extends Object ?
Obj[Key] extends Function ?
Obj[Key]
: DeepReadonly<Obj[Key]>
: Obj[Key]
} : never;
type obj = DeepReadonly<{
a: {
b: 1
}
}>