有没有办法在不使用数组文字类型表示法的情况下声明元组?



好的,所以这主要是出于我的好奇心。请参阅下面的代码:

const a: [string, number] = ["string", 1]; //valid
const b: Array<string, number> = ["string", 1]; //invalid
const c: Array<[string, number]> = ["string", 1] //invalid, it means [["string", 1]]

除非使用[]符号,否则似乎无法声明元组。我的下一个想法是寻找元组类型,但似乎没有内置任何东西。

你可以像这样声明一个Tuple类型:type Tuple<K, V> = [K, V]但这违背了整个想法。

也像:

let d: Array<string | number> = ["string", 1]

会编译,但您将能够为其分配类似["string", "another string", 1, 2, "stuff"]的东西。

更新 1:如 @jcalztype Tuple<K, V> = [K, V]所示,这是不正确的,因为它将元组类型的元素数量限制为 2。

究竟是什么"打败了type Tuple<K, V>的整个想法"? 是Tuple<>不允许任意数量的类型参数吗? 或者它在其定义中使用[]


以下是获得解决方案的一种可能途径,具体取决于您的用例:

type Tuple<A, B = never, C = never, D = never, E = never, F = never, G = never> =
[G] extends [never] ? [F] extends [never] ? [E] extends [never] ?
[D] extends [never] ? [C] extends [never] ? [B] extends [never] ?
[A] : [A, B] : [A, B, C] : [A, B, C, D] : [A, B, C, D, E] :
[A, B, C, D, E, F] : [A, B, C, D, E, F, G]

在这里,Tuple<>是一个条件类型,它使用默认泛型参数来允许您指定 1 到 7 个元组元素之间的任意位置:

const e: Tuple<string, number> = ["string", 1]; // okay

如果你需要更多的元素,你可以扩展上面的定义,尽管你永远无法得到任意数量的元素,没有像可变参数这样的东西,它们不是TypeScript的一部分(无论如何从2.9开始(。

或者这可能不算数,因为元组语法在定义中使用。 如果你想完全避免元组语法,你可以尝试创建一个类似于元组的类型......对于双元素情况,如下所示:

interface FakeTuple2<A, B> extends Array<A | B> {
readonly length: 2,
0: A,
1: B,
}

这足以满足许多目的的元组,具体取决于您的需求:

const f: FakeTuple2<string, number> = ["string", 1]; // okay

如果你想要可变数量的元素以及假元组,你可以使用上面的两种方法来获得类似的东西:

type StripNever<T> = Pick<T, { [K in keyof T]: T[K] extends never ? never : K }[keyof T]>
type FakeTuple<A, B = never, C = never, D = never, E = never, F = never, G = never> =
Array<A | B | C | D | E | F | G> & 
StripNever<{ 0: A, 1: B, 2: C, 3: D, 4: E, 5: F, 6: G }> & {
length: [G] extends [never] ? [F] extends [never] ? [E] extends [never] ?
[D] extends [never] ? [C] extends [never] ? [B] extends [never] ? 
1 : 2 : 3 : 4 : 5 : 6 : 7
}

它也适用于一到七个元素,并且可以扩展。


所以这些是给你的一些想法。 希望他们有帮助。 祝你好运!

相关内容

最新更新