网站搜索

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>;

相关文章