Typescript 中枚举的类型是什么?
What is the type of an enum in Typescript?
给定一个函数,其参数应该是 enum
。传入的 enum
可以有不同数量的属性。如何修复该参数的类型? enum
本身不是一个类型。
例如:
function (myEnum: mysteriousType){
//What is that mysteriousType ?
}
用例是构建一个通用方法来实例化枚举中的 dat.GUI 选项,无论枚举中的 string/number 类型如何。
根据你目前所说的(需要接受所有字符串/数字/异构枚举),我能做的最接近的事情是这样的:
type Enum<E> = Record<keyof E, number | string> & { [k: number]: string };
function acceptEnum<E extends Enum<E>>(
myEnum: E
): void {
// do something with myEnum... what's your use case anyway?
}
enum E { X, Y, Z };
acceptEnum(E); // works
如果你只知道它是 "some enum type",我不确定你要用 myEnum
做什么,但我想那是由你自己去想。
我是怎么想出这个的:我检查了一堆具体的 enum
类型,它们似乎具有带有字符串键和字符串或数值(正向映射)的属性,以及一个数字具有字符串值的索引键(数值的反向映射)。
const works: { X: 0, Y: 1, Z: 2, [k: number]: string } = E; // works
语言设计者可能进一步限制了这一点,因为反向映射只会产生在正向映射中看到的特定数字键和字符串值,但出于某种原因,它并没有像那样实现:
const doesntWork: { X: 0, Y: 1, Z: 2, [k: number]: 'X' | 'Y' | 'Z' } = E; // error
const alsoDoesntWork: { X: 0, Y: 1, Z: 2, 0: 'X', 1: 'Y', 2: 'Z' } = E; // error
所以我可以对枚举类型施加的最严格的约束是上面的E extends Enum<E>
。
请注意,此代码不适用于运行时不存在的 const enum
类型:
const enum F {U, V, W};
acceptEnum(F); // nope, can't refer to `F` by itself
还要注意上面的类型 (E extends Enum<E>
) 允许一些它可能不应该允许的事情:
acceptEnum({ foo: 1 }); // works
在上面,{foo: 1}
可能是一个类似于 enum Foo {foo = 1}
的数字枚举,但它没有反向映射,如果你依赖它,事情会在运行时爆炸。请注意,{foo: 1}
似乎没有索引签名,但它仍然匹配索引签名 implicitly。它不会匹配失败,除非你添加了一些明确的错误值:
acceptEnum({foo: 1, 2: 3}); // error, prop '2' not compatible with index signature
但这里无事可做。正如我上面提到的, enum
类型的实现目前并没有尽可能多地限制数字键,因此在编译时似乎没有办法区分具有良好反向映射的枚举和没有良好反向映射的枚举一.
希望对您有所帮助。祝你好运!
根据您的使用情况,这可能有效:(这是我使用的)
export function GetEnumValues<T>(enumType: T) {
// if your enum has string value, get rid of the "Exclude<>" wrapper
type ValType = T extends {[k: string]: infer X} ? Exclude<X, string> : any;
const entryNames = Object.keys(enumType).filter(key=>!/[0-9]+/.test(key[0]));
return entryNames.map(name=>enumType[name] as ValType );
}
用法:
enum Fruit {
Apple,
Grape,
Pear,
}
const enumVals = GetEnumValues(Fruit);
// the type of enumVals is: Fruit[]
编辑:在重新阅读您的问题时,这似乎不是您想要的。不过,将其保留在这里以供参考,因为它对于需要能够 return 传入给定枚举的“实例”的函数很有用(并且您不想在其中手动提供括号中的类型).
给定一个函数,其参数应该是 enum
。传入的 enum
可以有不同数量的属性。如何修复该参数的类型? enum
本身不是一个类型。
例如:
function (myEnum: mysteriousType){
//What is that mysteriousType ?
}
用例是构建一个通用方法来实例化枚举中的 dat.GUI 选项,无论枚举中的 string/number 类型如何。
根据你目前所说的(需要接受所有字符串/数字/异构枚举),我能做的最接近的事情是这样的:
type Enum<E> = Record<keyof E, number | string> & { [k: number]: string };
function acceptEnum<E extends Enum<E>>(
myEnum: E
): void {
// do something with myEnum... what's your use case anyway?
}
enum E { X, Y, Z };
acceptEnum(E); // works
如果你只知道它是 "some enum type",我不确定你要用 myEnum
做什么,但我想那是由你自己去想。
我是怎么想出这个的:我检查了一堆具体的 enum
类型,它们似乎具有带有字符串键和字符串或数值(正向映射)的属性,以及一个数字具有字符串值的索引键(数值的反向映射)。
const works: { X: 0, Y: 1, Z: 2, [k: number]: string } = E; // works
语言设计者可能进一步限制了这一点,因为反向映射只会产生在正向映射中看到的特定数字键和字符串值,但出于某种原因,它并没有像那样实现:
const doesntWork: { X: 0, Y: 1, Z: 2, [k: number]: 'X' | 'Y' | 'Z' } = E; // error
const alsoDoesntWork: { X: 0, Y: 1, Z: 2, 0: 'X', 1: 'Y', 2: 'Z' } = E; // error
所以我可以对枚举类型施加的最严格的约束是上面的E extends Enum<E>
。
请注意,此代码不适用于运行时不存在的 const enum
类型:
const enum F {U, V, W};
acceptEnum(F); // nope, can't refer to `F` by itself
还要注意上面的类型 (E extends Enum<E>
) 允许一些它可能不应该允许的事情:
acceptEnum({ foo: 1 }); // works
在上面,{foo: 1}
可能是一个类似于 enum Foo {foo = 1}
的数字枚举,但它没有反向映射,如果你依赖它,事情会在运行时爆炸。请注意,{foo: 1}
似乎没有索引签名,但它仍然匹配索引签名 implicitly。它不会匹配失败,除非你添加了一些明确的错误值:
acceptEnum({foo: 1, 2: 3}); // error, prop '2' not compatible with index signature
但这里无事可做。正如我上面提到的, enum
类型的实现目前并没有尽可能多地限制数字键,因此在编译时似乎没有办法区分具有良好反向映射的枚举和没有良好反向映射的枚举一.
希望对您有所帮助。祝你好运!
根据您的使用情况,这可能有效:(这是我使用的)
export function GetEnumValues<T>(enumType: T) {
// if your enum has string value, get rid of the "Exclude<>" wrapper
type ValType = T extends {[k: string]: infer X} ? Exclude<X, string> : any;
const entryNames = Object.keys(enumType).filter(key=>!/[0-9]+/.test(key[0]));
return entryNames.map(name=>enumType[name] as ValType );
}
用法:
enum Fruit {
Apple,
Grape,
Pear,
}
const enumVals = GetEnumValues(Fruit);
// the type of enumVals is: Fruit[]
编辑:在重新阅读您的问题时,这似乎不是您想要的。不过,将其保留在这里以供参考,因为它对于需要能够 return 传入给定枚举的“实例”的函数很有用(并且您不想在其中手动提供括号中的类型).