给定一个参数应该是enum
的函数。传入的enum
可以具有不同数量的属性。如何修复该参数的类型? enum
本身不是一种类型。
E.g。 :
function (myEnum: mysteriousType){
//What is that mysteriousType ?
}
<小时/> 用例是构建一个通用方法来实现枚举中的dat.GUI选项,无论枚举中的字符串/数字类型如何。
答案 0 :(得分:7)
根据你到目前为止所说的内容(需要接受所有字符串/数字/异构枚举),我能做的最接近的是:
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
如果您知道的是“某些枚举类型”,我不确定您将使用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
打字的实现目前并没有尽可能地约束数字键,所以在编译时似乎没有办法区分具有良好反向映射的枚举和没有反向映射的枚举。之一。
希望有所帮助。祝你好运!
答案 1 :(得分:0)
根据您的用例,这可能有效:(这是我使用的)
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[]
编辑:在重新阅读您的问题时,这似乎不是您想要的。不过,将其保留在此处以供参考,因为它对于需要能够返回传入的给定枚举的“实例”的函数很有用(并且您不想在括号中手动提供类型)。>