typescript - TypeScript - 将类型附加到元组类型的末尾
问题描述
是否可以编写一个将附加类型附加到给定元组类型的助手?
type A = Append<['a', 'b'], 'c'> // resulting in ['a', 'b', 'c']
我也有兴趣加入 2 元组类型:
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']
但是您已经询问了其他方式,这更棘手,但通过使用上面Shift
的方法是Unshift
可行的。考虑:
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 会抱怨无限调用
推荐阅读
- javascript - JavaScript 盒子游戏 - 内部 div 超出外部 div 边界
- java - AB 或 BA 但 DRY
- python-3.x - 在给定开始和结束时间的情况下计算并发会话
- python-attrs - Python Attr:使用其他属性的转换器?
- asp.net-core - 使用 Saml2p 与 IdentityServer4 集成 SAML
- python - 在 Tkinter 中循环并没有按我的预期工作
- r - R:使用 dcast 或 pivot_wider 进行整形的问题
- reactjs - Create React App 上的 Service Worker 不会在 safari 上加载视频
- javascript - 如何向节点/表达 mySQL 函数添加错误处理
- python - Numpy 替换值