无序元组类型

编程入门 行业动态 更新时间:2024-10-27 00:26:16
本文介绍了无序元组类型的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

限时送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:关键词]

本文发布于:2023-04-29 09:17:00,感谢您对本站的认可!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:类型

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!