![](/img/trans.png)
[英]How to define an array type with items of different types and with a specific order in TypeScript?
[英]How to define array with alternating types in TypeScript?
我想定义一个数组类型,它允许根据 position 使用不同的类型,但是以在某些数据结构中发现的重复、交替的方式。
例子:
[A, B, A, B, ...]
[A, B, C, A, B, C, ...]
这可能吗?
我知道我可以为 arrays 定义它,上面有固定数量的元素(没有省略号),并且
(A | B)[]
另一方面,将允许任何元素为 A 或 B 类型。
我试过这些:
[(A, B)...]
[...[A, B]]
[(A, B)*]
我想出了一些“有效”的东西,但这有点疯狂:
type Alternating<T extends readonly any[], A, B> =
T extends readonly [] ? T
: T extends readonly [A] ? T
: T extends readonly [A, B, ...infer T2]
? T2 extends Alternating<T2, A, B> ? T : never
: never
由于递归条件类型,这需要 TypeScript 4.1+。
幼稚的用法需要将值复制为T
参数的文字类型,这并不理想:
const x: Alternating<[1, 'a', 2], number, string> = [1, 'a', 2]
这似乎比仅仅写出[number, string, number]
作为类型更糟糕。 然而,在虚拟 function 的帮助下,可以避免重复:
function mustAlternate<T extends readonly any[], A, B>(
_: Alternating<T, A, B>
): void {}
const x = [1, 'a', 2] as const
mustAlternate<typeof x, number, string>(x)
我实际上并不建议在典型的代码库中依赖它(使用起来很尴尬,而且错误消息很糟糕)。 我大多只是通过它来查看类型系统可以延伸多远。
如果有人对如何使它不那么不稳定有任何建议,我全神贯注!
替代方法:
type MAXIMUM_ALLOWED_BOUNDARY = 50
type Mapped<
Tuple extends Array<unknown>,
Result extends Array<unknown> = [],
Count extends ReadonlyArray<number> = []
> =
(Count['length'] extends MAXIMUM_ALLOWED_BOUNDARY
? Result
: (Tuple extends []
? []
: (Result extends []
? Mapped<Tuple, Tuple, [...Count, 1]>
: Mapped<Tuple, Result | [...Result, ...Tuple], [...Count, 1]>)
)
)
type Result = Mapped<[string, number, number[]]>
// 3 | 6 | 9 | 12 | 15 | 18 | 21 | 24 | 27 | 30 | 33 | 36 | 39 | 42 | 45 | 48
type Test = Result['length']
/**
* Ok
*/
const test1: Result = ['a', 42, [1]]
const test2: Result = ['a', 42, [1], 'b', 43, [2]]
/**
* Fail
*/
const test3:Result = ['a'] // error
const fn = <T, U>(tuple: Mapped<[T, U]>) => tuple
fn([42, 'hello']) // ok
fn([42, 'hello','sdf']) // expected error
Mapped
- 丑陋的名字,但工作:D。 创建元组的所有允许状态的联合。 每个允许的元组 state 的长度可以除以 3: length%3===0 // true
。 你可以定义任何你想要的元组,有 4 个值,5 个等等......
每次迭代我都会将Count
数组增加 1。这就是我知道何时停止递归迭代的方式。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.