用数字枚举创建Typescript`Record <>`类型

Ric*_*ick 5 enums typescript

在Typescript中,可以使用字符串枚举创建记录类型:

enum AxisLabel { X = "X", Y = "Y" }
export const labelLookup: Record<AxisLabel, string> = {
  [AxisLabel.X]: "X axis",
  [AxisLabel.Y]: "Y Axis"
};
Run Code Online (Sandbox Code Playgroud)

我需要创建一个Record与上述对象类似的对象,但是我不希望使用字符串enum

当我尝试这样的事情:

enum AxisLabel { X, Y }
export const labelLookup: Record<AxisLabel, string> = {
  [AxisLabel.X]: "X axis",
  [AxisLabel.Y]: "Y Axis"
};
Run Code Online (Sandbox Code Playgroud)

Typescript产生以下错误:

Type 'AxisLabel' does not satisfy the constraint 'string'.

可以使用数字和字符串作为成员名称来创建JS对象。

我希望在Typescript中做同样的事情,但不要求助于不安全的强制或强制类型转换。如何在Typescript中创建数字枚举Record <>类型而不使用字符串枚举any或类型转换?

jca*_*alz 7

更新:TypeScript 2.9 添加了numbersymbol作为有效键类型的支持,因此,只要您使用的是TypeScript 2.9或更高版本,上面的代码就不会再出现错误,并且不再需要此答案。

对于TypeScript 2.8及以下版本:


不管您相信与否,JavaScript中的对象键始终是字符串(可以Symbol是s),即使是数组也是如此。当您将非字符串值作为键传递时,它将首先被强制为字符串。但是人们当然希望数字键有意义,尤其是对于数组。打字稿样的反映了这种不一致的理念:通常你只能指定字符串值的键(如在映射类型一样Record<K,V>)。当这些情况相互作用时,您会变得很奇怪。

这是我有时要做的一件事:使用以下元组类型显式表示从数字到字符串的强制转换:

export type NumericStrings = ["0","1","2","3","4","5","6","7","8","9","10"] // etc
Run Code Online (Sandbox Code Playgroud)

请注意,您可以根据需要延长该时间。然后,您可以使用查找类型将数字类型转换为其对应的字符串,以用于映射类型。像这样:

export enum AxisLabel { X, Y }

// note the key is NumericStrings[AxisLabel], not AxisLabel    
export const labelLookup: Record<NumericStrings[AxisLabel], string> = {
  [AxisLabel.X]: "X axis",
  [AxisLabel.Y]: "Y Axis"
};
Run Code Online (Sandbox Code Playgroud)

那没有错误。如果检查的类型labelLookup,它将显示为Record<"0" | "1", string>。当您尝试索引到时labelLookup,会发生以下预期的事情:

labelLookup[AxisLabel.X]; // okay
labelLookup[0]; // okay
labelLookup["0"]; // also okay

labelLookup[10]; // error
labelLookup.X; //error
Run Code Online (Sandbox Code Playgroud)

希望能有所帮助;祝好运!


Tit*_*mir 6

记录的定义非常具体,键必须可分配给字符串,因此无法Record与数字一起使用,更一般地,映射类型中的键必须是字符串。

您可以使用常规索引签名,但不能将索引签名限制为除字符串或数字之外的任何内容(根据语言规范),这意味着任何数字都有效,而不仅仅是枚举值:

export const labelLookup: { [index: number]: string } = {
    [AxisLabel.X]: "X axis",
    [AxisLabel.Y]: "Y Axis",
    [3] = "" // Also works but you don't want that
};
Run Code Online (Sandbox Code Playgroud)