好的,所以这主要是出于我的好奇心。请参阅下面的代码:
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
}
它也适用于一到七个元素,并且可以扩展。
所以这些是给你的一些想法。 希望他们有帮助。 祝你好运!