好吧,这确实需要recursive conditional types,但TypeScript尚不支持。如果要使用它们,请at your own risk。通常,我宁愿写一个应该递归的类型,然后将其展开到固定的深度。因此,我写了type F<X> = ...F<X>...
而不是type F<X> = ...F0<X>...; type F0<X> = ...F1<X>...;
。
要编写此代码,我想对元组使用基本的“列表处理”类型,即Cons<H,T>
将类型H
放在元组T
之前; Head<T>
获取元组T
的第一个元素,Tail<T>
获取元组T
的第一个元素被删除。您可以这样定义:
type Cons<H,T> = T extends readonly any[] ? ((h: H,...t: T) => void) extends ((...r: infer R) => void) ? R : never : never;
type Tail<T extends readonly any[]> = ((...t: T) => void) extends ((h: any,...r: infer R) => void) ? R : never;
type Head<T extends readonly any[]> = T[0];
然后递归类型将如下所示:
/* type ExcludeFromTupleRecursive<T extends readonly any[],E> =
T["length"] extends 0 ? [] :
ExcludeFromTupleRecursive<Tail<T>,E> extends infer X ?
Head<T> extends E ? X : Cons<Head<T>,X> : never; */
想法是:取元组T
的尾巴并对其执行ExcludeFromTupleRecursive
。那是递归。然后,要得到结果,则当且仅当它与E
不匹配时,才应在元组的开头添加前缀。
但是那是非法的循环,所以我像这样展开它:
type ExcludeFromTuple<T extends readonly any[],E> = T["length"] extends 0 ? [] : X0<Tail<T>,E> extends infer X ? Head<T> extends E ? X : Cons<Head<T>,X> : never;
type X0<T extends readonly any[],E> = T["length"] extends 0 ? [] : X1<Tail<T>,X> : never;
type X1<T extends readonly any[],E> = T["length"] extends 0 ? [] : X2<Tail<T>,X> : never;
type X2<T extends readonly any[],E> = T["length"] extends 0 ? [] : X3<Tail<T>,X> : never;
type X3<T extends readonly any[],E> = T["length"] extends 0 ? [] : X4<Tail<T>,X> : never;
type X4<T extends readonly any[],E> = T["length"] extends 0 ? [] : X5<Tail<T>,X> : never;
type X5<T extends readonly any[],E> = T["length"] extends 0 ? [] : X6<Tail<T>,X> : never;
type X6<T extends readonly any[],E> = T["length"] extends 0 ? [] : X7<Tail<T>,X> : never;
type X7<T extends readonly any[],E> = T["length"] extends 0 ? [] : X8<Tail<T>,X> : never;
type X8<T extends readonly any[],E> = T["length"] extends 0 ? [] : X9<Tail<T>,X> : never;
type X9<T extends readonly any[],E> = T["length"] extends 0 ? [] : XA<Tail<T>,X> : never;
type XA<T extends readonly any[],E> = T["length"] extends 0 ? [] : XB<Tail<T>,X> : never;
type XB<T extends readonly any[],E> = T["length"] extends 0 ? [] : XC<Tail<T>,X> : never;
type XC<T extends readonly any[],E> = T["length"] extends 0 ? [] : XD<Tail<T>,X> : never;
type XD<T extends readonly any[],E> = T["length"] extends 0 ? [] : XE<Tail<T>,X> : never;
type XE<T extends readonly any[],E> = T; // bail out
玩得开心吗?让我们看看它是否有效:
type DepressingJourney = ExcludeFromTuple<Journey,"don't">;
// type should be ['stop','believing']
type SlicedPi = ExcludeFromTuple<[3,1,4,5,9,2,6,3,8,7,9],1 | 9>
// type SlicedPi = [3,7]
对我很好。希望能有所帮助。祝你好运!
Link to code
本文链接:https://www.f2er.com/3054644.html