javascript - TypeScript:如何在编译时为类型检查声明固定大小的数组
更新:这些检查是针对编译时的,而不是在运行时。在我的示例中,所有失败的情况都在编译时被捕获,我期望其他应该失败的情况也有类似的行为。
假设我正在编写一个类似表格的类,我希望类的所有成员都是相同长度的数组,类似于:
class MyClass {
tableHead: string[3]; // expect to be a 3 element array of strings
tableCells: number[3]; // expect to be a 3 element array of numbers
}
到目前为止,我找到的最接近的解决方案是:
class MyClass {
tableHead: [string, string, string];
tableCells: [number, number, number];
}
let bar = new MyClass();
bar.tableHead = ['a', 'b', 'c']; // pass
bar.tableHead = ['a', 'b']; // fail
bar.tableHead = ['a', 'b', 1]; // fail
// BUT these also pass, which are expected to fail at compile time
bar.tableHead = ['a', 'b', 'c', 'd', 'e']; // pass
bar.push('d'); // pass
bar.push('e'); // pass
还有更好的想法吗?
答案#1
更新2:从3.4版本开始,原贴所要求的现在可以通过简洁的语法完全实现(Playground链接):
class MyClass {
tableHead: readonly [string, string, string]
tableCells: readonly [number, number, number]
}
更新 1:从版本 2.7 开始,TypeScript 现在可以区分不同大小的列表。
我认为不可能对元组的长度进行类型检查。以下是 TypeScript 作者对此问题的看法。
我认为你所要求的并不是必要的。假设你定义这种类型
type StringTriplet = [string, string, string]
并定义该类型的变量:
const a: StringTriplet = ['a', 'b', 'c']
你不能从那个三元组中得到更多变量,例如
const [one, two, three, four] = a;
会报错,而这个则如预期不会:
const [one, two, three] = a;
我认为能力无法限制长度的唯一问题情况是,例如,当你对三元组进行 map 操作时
const result = a.map(/* some pure function */)
并且期望 result 有 3 个元素,而实际上它可能有超过 3 个。然而,在这种情况下,你无论如何都将 a 当作集合来处理,而不是元组,所以这并不是元组语法的正确用例。
答案#2
来自 TypeScript:我可以以编程方式定义一个 n 长度的元组类型吗,长度是动态的:
type Tuple<TItem, TLength extends number> = [TItem, ...TItem[]] & { length: TLength };
type Tuple9<T> = Tuple<T, 9>;
