我正在尝试实现一些类似于以下功能:
enum MyEnum {
ONE = "ONE",
TWO = "TWO"
}
interface MyInterface<T extends enum> { //Obviously wrong syntax
value: T; //Use a single value of the enum
values: Record<T, number>; //Use all of the keys of the enum
optionalValues: Record<T?, number>; //Use only the keys of the enum, but not necessarily all of them.
}
const a : MyInterface<MyEnum> = {
value: "ONE", //OK
values: {
ONE: 1, //OK
TWO: 2,
THREE: 3 //NOT OK
},
optionalValues: {
ONE: 111, //OK
THREE: 3 //NOT OK
}
}
const b : MyInterface<MyEnum> = {
value: MyEnum.ONE, //OK
values: {
ONE: 1, //Not ok - not all enum values used
},
optionalValues: {
[MyEnum.ONE]: 111, //Ok, and generally this is the way I want to be using this.
}
}
也就是说-我希望能够使用枚举来指定键列表,然后将接口定义为包含这些键的对象。
即。
const iceCreams = MyInterface<IceCreamFlavours> = {
...
}
const fruit = MyInterface<FruitTypes> = {
...
}
我该如何实现?这似乎是一个相当普遍的用例。
答案 0 :(得分:1)
没有enum
约束。枚举可以是string
或number
,因此约束string | number
是我们能做的最好的事情:
interface MyInterface<T extends string | number> {
value: T; //Use a single value of the enum
values: Record<T, number>; //Use all of the keys of the enum
optionalValues: Partial<Record<T, number>>; //Use only the keys of the enum, but not necessarily all of them.
}
enum MyEnum {
ONE = "ONE",
TWO = "TWO"
}
const a : MyInterface<MyEnum> = {
value: MyEnum.ONE, //OK
values: {
[MyEnum.ONE]: 1, //OK
[MyEnum.TWO]: 2,
[MyEnum.THREE]: 3 //NOT OK
},
optionalValues: {
[MyEnum.ONE]: 111, //OK
[MyEnum.THREE]: 3 //NOT OK
}
}
我们还可以使用枚举成员名称,但是我们必须传入枚举容器对象的类型,而不是枚举的类型。
interface MyInterface<T extends Record<keyof T, string | number>> { // enum like object
value: keyof T; //Use a single value of the enum
values: Record<keyof T, number>; //Use all of the keys of the enum
optionalValues: Partial<Record<keyof T, number>>; //Use only the keys of the enum, but not necessarily all of them.
}
enum MyEnum {
ONE = "ONE",
TWO = "TWO"
}
const a : MyInterface<typeof MyEnum> = {
value: "ONE", //OK
values: {
"ONE": 1, //OK
"TWO": 2,
"THREE": 3 //NOT OK
},
optionalValues: {
"ONE": 111, //OK
"THREE": 3 //NOT OK
}
}