TypeScript-将类型追加到元组类型的末尾



是否可以编写一个助手,将附加类型附加到给定的元组类型?

type A = Append<['a', 'b'], 'c'> // resulting in ['a', 'b', 'c']

我也有兴趣加入两种元组类型:

type B = Join<['a', 'b'], ['c', 'd']> // resulting in ['a', 'b', 'c', 'd']

在TS中,编写将从元组中移位和取消移位元素的函数非常简单。考虑:

type Shift<T extends Array<any>> 
= ((...a: T) => any) extends ((a: any, ...result: infer Result) => any) 
? Result 
: never;
type Unshift<A, T extends Array<any>> 
= ((a: A, ...b: T) => any) extends ((...result: infer Result) => any) 
? Result 
: never;
type A = Shift<['a', 'b', 'c']> // A is ['b','c']
type B = Unshift<'a', A> // B is again ['a', 'b', 'c']

但您已经询问了其他方法,这更棘手,但通过使用上面的ShiftUnshift是可行的。考虑:

type Append<
T extends any[]
, A
, ReducedT extends any[] = T
, Result extends any[] = [A]
, Rest extends any[] = Shift<ReducedT>
, Last extends T[keyof T] = T[Rest['length']]
> = {
[K in keyof ReducedT]: Rest['length'] extends 0 ? Unshift<Last, Result> : Append<T, A, Rest, Unshift<Last, Result>> 
}[0]
type R = Append<['a', 'b', 'c'], 'd'>
// ['a', 'b', 'c', 'd']
type Merge<
A extends any[]
, B extends any[]
, ReducedA extends any[] = A
, Result extends any[] = B
, Rest extends any[] = Shift<ReducedA>
, Last extends A[keyof A] = A[Rest['length']]
> = {
[K in keyof ReducedA]: Rest['length'] extends 0 ? Unshift<Last, Result> : Merge<A, B, Rest, Unshift<Last, Result>> 
}[0]
type AB = Merge<['a', 'b', 'c'], ['d','e','f']>
// ['a', 'b', 'c', 'd', 'e','f']

操场上有完整的代码。

这两种类型都是基于递归类型的,例如采用第一种类型Append:

  • ReducedT是一个数组,我们将使用它从原始数组中取出元素
  • Result-这是我们的最后一个数组,我们把东西放在它上面(注意,我们从[A]开始,所以从元素开始,我们想最后一个
  • Rest-它表示ReducedT的下一次迭代,所以我们移出一个元素
  • Last-原始数组中的最后一个元素
  • Rest['length'] extends 0 ? Unshift<Last, Result> : Append<T, A, Rest, Unshift<Last, Result>>-每次迭代都会检查我们的缩减数组是否不为空,如果是,我们最后一次取消移位并结束递归,如果不是空,当我们从一个取消移位到第二个时,我们用较小的ReducedT和较大的Result再次追加
  • [K in keyof ReducedT]在这里只是为了欺骗TS类型的系统,因为如果没有它,TS会抱怨无限调用😎

最新更新