问题描述
限时送ChatGPT账号..我只是在研究 Typescript 类型,我想知道如何定义一个类型,它是一个元组但具有无序元素类型.
我的意思是,拥有
type SimpleTuple = [number, string];const tup1: SimpleTuple = [7, `7`];//有效的const tup2: SimpleTuple = [`7`, 7];//'string' 不能赋值给 'number'//反之亦然
这在很多情况下都很有用,但是如果我不关心顺序或者我需要它是无序的怎么办.
上面的例子很简单,因为我可以定义
type SimpleUnorderedTuple = [数字,字符串] |[字符串,数字];const tup1: SimpleUnorderedTuple = [7, `7`];//有效的const tup2: SimpleUnorderedTuple = [`7`, 7];//有效的
但是,我可能有一堆类型......它们的组合逻辑会很痛苦
type ABunchOfTypes = 'these' |'是' |'一些' |'话' |'只是' |'为' |'的' |'例子';类型 ComplexUnorderedTuple =['these', 'are', 'some', 'words', 'just', 'for', 'the', 'example'] |['these', 'are', 'some', 'words', 'just', 'for', 'example', 'the'] |//等等 ...
这太疯狂了.有 !n
种可能的组合,其中 n
是元素的数量(我猜,我数学不太好!).
我正在努力实现类似的目标
type ABunchOfTypes = 'these' |'是' |'一些';输入 UnorderedTuple=;//...类型 ComplexUnorderedTuple = UnorderedTuple;
我在这篇文章
中找到<块引用>我们添加到元组变量的任何后续值都可以是任何预定义的元组类型,没有特定的顺序.
但是我无法复制.如果我定义了一个包含两个元素的元组,如果 n
大于(或等于)元组长度,则不允许访问第 n 个位置.
如果您正在寻找联合的排列类型,这将为您提供:
type ABunchOfTypes = 'these' |'是' |'一些' |'话' |'只是';type PushFront=((head: HeadT, ...tail: TailT) => void) extends ((...arr: infer ArrT) => void) ?ArrT:从不;类型CalculatePermutations= {[k 在 U]: ([排除<U,k>]扩展[从不]?PushFront<ResultT,k>:计算排列<排除,PushFront>)}[U];var 测试:CalculatePermutations= ['are', 'these', 'just', 'words', 'some'];
您可以尝试在此游乐场.>
但是,这种方法存在局限性;我的实验表明 TypeScript 最多可以处理 7 个字符串的并集.有 8 个或更多字符串时,将显示错误.
更新
如果没有重复"是需要的,简单多了.
type ABunchOfTypes = 'these' |'是' |'一些' |'话' |'只是';type PushFront=((head: HeadT, ...tail: TailT) => void) extends ((...arr: infer ArrT) => void) ?ArrT:从不;type NoRepetition= {[k in U]:PushFront<ResultT,k>|NoRepetition<Exclude<U,k>,PushFront<ResultT,k>}[U];//好的var 测试:NoRepetition= ['are', 'these', 'just', 'words', 'some'];test = ['are', 'these', 'just'];测试 = ['是'];//不好test = ['are', 'these', 'are'];
请参阅此游乐场链接.
此外,使用即将推出的 TypeScript 4 语法,它仍然可以简化:
type ABunchOfTypes = 'these' |'是' |'一些' |'话' |'只是';//对于打字稿 4type NoRepetition= {[k in U]: [k, ...ResultT] |NoRepetition<Exclude<U,k>,[k,...ResultT]>}[U];//好的var 测试:NoRepetition= ['are', 'these', 'just', 'words', 'some'];test = ['are', 'these', 'just'];测试 = ['是'];//不好test = ['are', 'these', 'are'];
请参阅此 游乐场链接.
更新 2
以上两个假设你要求数组非空.如果你还想允许空数组,你可以这样做:
type ABunchOfTypes = 'these' |'是' |'一些' |'话' |'只是';//对于打字稿 4type NoRepetition= 结果T |{[k in U]:NoRepetition<Exclude<U,k>,[k,...ResultT]>}[U];//好的var 测试:NoRepetition= ['are', 'these', 'just', 'words', 'some'];test = ['are', 'these', 'just'];测试 = ['是'];测试 = [];//不好test = ['are', 'these', 'are'];
看到这个游乐场链接.
可以将 U extends string
替换为 U extends keyof any
以支持字符串、数字和符号的联合类型,但当前 TypeScript 的限制使其无法实现超越这一点.
I am just digging into Typescript typings and I wondered how to define a type which is a tuple but with unordered element types.
I mean, having
type SimpleTuple = [number, string];
const tup1: SimpleTuple = [7, `7`]; // Valid
const tup2: SimpleTuple = [`7`, 7]; // 'string' is not assignable to 'number'
// and vice-versa
This is useful in many cases, but what if I don't care about order or I need it to be unordered.
The example above is quite trivial since I could define
type SimpleUnorderedTuple = [number, string] | [string, number];
const tup1: SimpleUnorderedTuple = [7, `7`]; // Valid
const tup2: SimpleUnorderedTuple = [`7`, 7]; // Valid
However, I may have a bunch of types... A combinatory logic uppon them would be painful
type ABunchOfTypes = 'these' | 'are' | 'some' | 'words' | 'just' | 'for' | 'the' | 'example';
type ComplexUnorderedTuple =
['these', 'are', 'some', 'words', 'just', 'for', 'the', 'example'] |
['these', 'are', 'some', 'words', 'just', 'for', 'example', 'the'] |
// and so on ...
This is insane. There are !n
possible combinations, where n
is the number of elements (I guess, I am not too good at maths!).
I am trying to achieve something like
type ABunchOfTypes = 'these' | 'are' | 'some';
type UnorderedTuple<T> = ; //...
type ComplexUnorderedTuple = UnorderedTuple<ABunchOfTypes>;
I found in this article
Any subsequent value we add to the tuple variable can be any of the predefined tuple types in no particular order.
But I couldn't reproduce. If I define a tuple of two elements, I am not allowed to access to the nth position, if n
is greater than (or equal) the tuple length.
If you are looking for permutation type of a union, this will give you exactly that:
type ABunchOfTypes = 'these' | 'are' | 'some' | 'words' | 'just';
type PushFront<TailT extends any[], HeadT> =
((head: HeadT, ...tail: TailT) => void) extends ((...arr: infer ArrT) => void) ? ArrT : never;
type CalculatePermutations<U extends string, ResultT extends any[] = []> = {
[k in U]: (
[Exclude<U, k>] extends [never] ?
PushFront<ResultT, k> :
CalculatePermutations<Exclude<U, k>, PushFront<ResultT, k>>
)
}[U];
var test: CalculatePermutations<ABunchOfTypes> = ['are', 'these', 'just', 'words', 'some'];
You can try it in this Playground.
There is a limitation to this approach, however; my experiment showed that TypeScript can at most process a union of 7 strings. With 8 or more strings, an error will shown.
Update
If "no repetition" is what is needed, it is a lot simpler.
type ABunchOfTypes = 'these' | 'are' | 'some' | 'words' | 'just';
type PushFront<TailT extends any[], HeadT> =
((head: HeadT, ...tail: TailT) => void) extends ((...arr: infer ArrT) => void) ? ArrT : never;
type NoRepetition<U extends string, ResultT extends any[] = []> = {
[k in U]: PushFront<ResultT, k> | NoRepetition<Exclude<U, k>, PushFront<ResultT, k>>
}[U];
// OK
var test: NoRepetition<ABunchOfTypes> = ['are', 'these', 'just', 'words', 'some'];
test = ['are', 'these', 'just'];
test = ['are'];
// Not OK
test = ['are', 'these', 'are'];
See this Playground Link.
Also, with the upcoming TypeScript 4 syntax, it can be simplified still:
type ABunchOfTypes = 'these' | 'are' | 'some' | 'words' | 'just';
// for TypeScript 4
type NoRepetition<U extends string, ResultT extends any[] = []> = {
[k in U]: [k, ...ResultT] | NoRepetition<Exclude<U, k>, [k, ...ResultT]>
}[U];
// OK
var test: NoRepetition<ABunchOfTypes> = ['are', 'these', 'just', 'words', 'some'];
test = ['are', 'these', 'just'];
test = ['are'];
// Not OK
test = ['are', 'these', 'are'];
See this Playground Link.
Update 2
The above two assumes that you require the array to be non-empty. If you also want to allow empty array, you can do it like this:
type ABunchOfTypes = 'these' | 'are' | 'some' | 'words' | 'just';
// for TypeScript 4
type NoRepetition<U extends string, ResultT extends any[] = []> = ResultT | {
[k in U]: NoRepetition<Exclude<U, k>, [k, ...ResultT]>
}[U];
// OK
var test: NoRepetition<ABunchOfTypes> = ['are', 'these', 'just', 'words', 'some'];
test = ['are', 'these', 'just'];
test = ['are'];
test = [];
// Not OK
test = ['are', 'these', 'are'];
See this Playground Link.
It is possible to replace U extends string
by U extends keyof any
to support union types of strings, numbers and symbols, but the current limitation of TypeScript makes it impossible to go beyond this.
这篇关于无序元组类型的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
更多推荐
[db:关键词]
发布评论