在打字稿中,可以使用字符串枚举创建记录类型:
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添加了对number
和symbol
作为有效的密钥类型的支持,因此上面的代码不再给出错误,并且只要您不再需要这个答案,只要您是您使用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"
}