enum MyEnum {
First, // default value of this is 0
Second, // default value of this is 1
}
let obj: { [key in MyEnum]?: any} = { [MyEnum.First]: 1 };
obj[MyEnum.First] = 1; // can use the enum...
obj[0] = 1; // but can also use the enum value,
// as it is a numeric enum by default
注意我们是如何直接使用枚举值的:这是一个数字枚举。这并不意味着我们可以使用任何整数键:
obj[42] = 1;
// Element implicitly has an 'any' type because
// expression of type '42' can't be used to index type '{ 0?: any; 1?: any; }'.
// Property '42' does not exist on type '{ 0?: any; 1?: any; }'.
enum MyEnum
{
First = 1,
Second = "YES"
}
let obj: { [key in MyEnum]?: any} = { [MyEnum.First]: 1, [MyEnum.Second]: 2 };
obj[1] = 0;
obj["YES"] = 0;
这里的类型是:
{
1?: any;
YES?: any;
}
您可以使用readonly按预期选择不变性:
let obj: { readonly [key in MyEnum]?: any} = {
[MyEnum.First]: 1,
};
obj[MyEnum.First] = 2;
// Cannot assign to '1' because it is a read-only property.
...这使得所有枚举键readonly:
{
readonly 1?: any;
readonly 2?: any;
}
自动递增陷阱
小心自动增量!
enum MyEnum
{
First = 1,
Second,
Third = 2,
}
let obj: { [key in MyEnum]?: any} = {
[MyEnum.First]: 10,
[MyEnum.Second]: 20,
[MyEnum.Third]: 30,
};
// {1: 10, 2: 30}
enum MyEnum {
xxx = "xxx",
yyy = "yyy",
zzz = "zzz",
}
type myType = ...; // Fill here
const o: myType = { // keys should be in MyEnum, values: number
[MyEnum.xxx]: 2,
"hi": 5, // <--- Error: complain on this one, as "hi" is not in enum
}
o[MyEnum.yyy] = 8; // Allow it to be modified later
enum EnumString {
a="a",
b="b"
}
enum EnumNum {
a,
b
}
type Type = "a" | "b"
let x1:{[k in EnumString]?:any }={a:1} //working
let x2:{[k in EnumNum]?:any }={a:1} //error: Type '{ a: number; }' is not assignable to type '{ 0?: any; 1?: any; }'
let x3:{[k in Type]?:any }={a:1} //working; defining a union type is easer than defining an enum string
let y1:{[k: EnumString]?:any }={a:1}
let y2:{[k: EnumNum]?:any }={a:1}
let y3:{[k in Type]?:any }={a:1}
let z1:{[k in keyof typeof EnumString]?:any }={a:1}
let z2:{[k in keyof typeof EnumNum]?:any }={a:1}
let z3:{[k: keyof typeof Type]?:any }={a:1}
5条答案
按热度按时间yyyllmsg1#
Since 2018,在Typescript中有一种更简单的方法,无需使用
keyof typeof
:要不必包括所有密钥:
in Enum
与keyof typeof Enum
本节将详细介绍
in Enum
和keyof typeof
之间的区别,以及为什么keyof typeof
可能是一个不好的选择。主要的区别是
in Enum
编译为枚举 * 值 *,而keyof typeof
编译为枚举 * 键 *,但是您应该注意一些更微妙的功能。对于
keyof typeof
,您不能在以后修改枚举属性:...除非您使用
-readonly
:但是您可以使用任何其他整数键就好了!?
这是因为
keyof typeof
将编译为:注意
[x: number]
和readonly
属性的存在。如果使用字符串枚举,则[x: number]
属性不存在。相反,使用
in Enum
,可以修改对象:注意我们是如何直接使用枚举值的:这是一个数字枚举。这并不意味着我们可以使用任何整数键:
如果我们看看类型,这就很明显了:
只有
0
和1
,我们的枚举值是允许的,其他值是禁止的。这更符合你对枚举工作的期望,不像keyof typeof
,没有什么令人惊讶的。当然,这也适用于字符串和异构枚举:
这里的类型是:
您可以使用
readonly
按预期选择不变性:...这使得所有枚举键
readonly
:自动递增陷阱
小心自动增量!
20
值消失了!在TS中,数字枚举是自动递增的,但不考虑重复的值。这意味着MyEnum.Second
和MyEnum.Third
的值是2
! TS没有警告这一点,所以请确保在可能的情况下lint它。总结
|
in Enum
|keyof typeof Enum
|| - ------|- ------|
| 编译为枚举值|编译为枚举键|
| * * 不允许枚举之外的值**|如果使用数值枚举,则可以允许枚举之外的数值|
| * * 可以修改对象,不可变选择
readonly
**|如果没有-readonly
,则无法修改枚举属性。枚举之外的其他数值可以是|| 枚举值可能会因为自动递增而发生冲突|枚举值可能会因为自动递增而发生冲突|
如果可能,请使用
in Enum
。如果您的代码库使用keyof typeof Enum
,请注意这些陷阱。9fkzdhlc2#
是的。只要输入
从Typescript 2.1开始就可以使用
keyof
关键字。更多细节请参见TypeScript documentation。仅使用keyof
作为枚举将不起作用(您将获得enum
类型的键,而不是枚举常量),因此您必须键入keyof typeof
。vaj7vani3#
简短回答:
详细答案(包含详细信息):
我也遇到了同样的问题。我想让下面的代码工作。
从other answer开始讨论这个问题,我得到:
但是这会让
o is missing "yyy"
很麻烦,所以我需要告诉它这个对象会有一些枚举键,而不是所有的,所以我需要加上?
来得到:它一直工作得很好,直到我在代码末尾添加了一行代码,以便在对象第一次创建后对其进行修改。现在它抱怨说,通过
keyof
继承的类型具有readonly
属性,并且在第一次创建后我无法触及这些属性!|实际上,将鼠标悬停在Typescript Playground中的myType
上,将显示为:现在,要删除不需要的
readonly
,我发现可以使用:直到我玩过Typescript实用程序类型,并找到了我想要的!
:)
7gyucuyw4#
对于那些正在寻找一种方法来获得
enum
的keys
而不是它的value
的人来说,你只需要从这个改变:改为:
92dk7w1h5#
事实上,它对我很有效,没有任何变通办法。
以下是一些案例:
重要的是要注意到,“z1”的情况下,即使它工作得很好,但你不能修改它以后,因为它是一个只读。你可以使用关键字
-readonly
来删除这个约束。我创建了一个 typescript Playground,让您自己查看不同案例的问题