使用数字枚举创建打字稿"记录<>"类型



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

enum AxisLabel { X = "X", Y = "Y" }
export const labelLookup: Record<AxisLabel, string> = {
  [AxisLabel.X]: "X axis",
  [AxisLabel.Y]: "Y Axis"
};

我需要创建一个类似于上面一个的Record对象,但是我不想使用字符串枚举

当我尝试这样的事情时:

enum AxisLabel { X, Y }
export const labelLookup: Record<AxisLabel, string> = {
  [AxisLabel.X]: "X axis",
  [AxisLabel.Y]: "Y Axis"
};

打字稿产生以下错误:

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

可以将JS对象创建为数字和字符串作为其成员名称。

我希望在打字稿中做同样的事情,但不要诉诸于不安全的强制或类型的铸件。如何在不使用字符串枚举, any或类型casts的情况下创建数字枚举记录&lt;>类型?

update:typescript 2.9添加了对numbersymbol作为有效的密钥类型的支持,因此上面的代码不再给出错误,并且只要您不再需要这个答案,只要您是您使用Typescript 2.9或更高。

对于打字稿2.8和以下:


JavaScript中的对象键是,无论信不信由与否,始终字符串(好的,或Symbol s),即使对于数组也是如此。当您将非弦值作为键传递时,它会首先将其胁迫。但是,当然,人们期望数字键有意义,尤其是对于数组。Typescript类型反映了这种不一致的理念:通常您只能指定字符串值值键(例如在诸如Record<K,V>之类的映射类型中)。当这些情况相互作用时,您会变得很奇怪。

这是我有时完成的一件事:用以下元组类型明确表示从数字到字符串的胁迫:

export type NumericStrings = ["0","1","2","3","4","5","6","7","8","9","10"] // etc

请注意,只要需要它,就可以扩展它。然后,您可以使用查找类型将数字类型转换为其字符串对应物,以用于映射类型。喜欢:

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

无错误的工作。如果您检查labelLookup的类型,则显示为Record<"0" | "1", string>。当您尝试将labelLookup索引时,以下主要指出的事情发生了:

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

希望有帮助;祝你好运!

记录的定义非常具体,即键必须分配给字符串,因此没有办法将Record与一个数字一起使用,更一般而言,映射类型中的密钥必须是一个细绳。

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

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

使用枚举作为Record

的一部分的另一种方法
enum AxisLabel { X, Y }
export const labelLookup: Record<AxisLabel[keyof AxisLabel & number], string> = {
  [AxisLabel.X]: "X axis",
  [AxisLabel.Y]: "Y Axis"
}

enum AxisLabel { X, Y }
type XorY = typeof AxisLabel.X | typeof AxisLabel.Y
export const labelLookup: Record<XorY, string> = {
  [AxisLabel.X]: "X axis",
  [AxisLabel.Y]: "Y Axis"
}

最新更新