Typescript 中的枚举类型是什么? [英] What is the type of an enum in Typescript?
问题描述
给定一个函数,它的参数应该是一个 enum
.传入的 enum
可以有不同数量的属性.如何修复该参数的类型?enum
本身不是一个类型.
Given a function that has an argument supposed to be an enum
. The enum
passed in can have different numbers of properties. How to fix the type of that argument ? enum
itself is not a type.
例如:
function (myEnum: mysteriousType){
//What is that mysteriousType ?
}
<小时>用例是构建一个通用方法来实例化 dat.GUI 枚举中的选项,无论枚举中的字符串/数字类型如何.
The use case is to build a generic method to instantiate dat.GUI options from an enum, whatever the string/number type in the enum.
推荐答案
根据你到目前为止所说的(需要接受所有字符串/数字/异构枚举),我能做的最接近的事情是这样的:>
With what you've stated so far (needs to accept all string / numeric / heterogeneous enums), the closest I can do is something like this:
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
做什么,但我想这取决于你来弄清楚.
I'm not sure what you're going to do with myEnum
if all you know is that it's "some enum type", but I guess that's up to you to figure out.
我是如何想出这个的:我检查了一堆具体的 enum
类型,它们似乎具有带有字符串键和字符串或数字值的属性(前向映射),以及一个带有字符串值的数字索引键(数字值的反向映射).
How I came up with this: I examined a bunch of concrete enum
types, and they seem to have properties with string keys and string or numeric values (the forward mapping), as well as a numeric index key with string values (the reverse mapping for numeric values).
const works: { X: 0, Y: 1, Z: 2, [k: number]: string } = E; // works
语言设计者可能进一步限制了这一点,因为反向映射只会产生正向映射中看到的特定数字键和字符串值,但出于某种原因,它没有像那样实现:
The language designers might have constrained this further, since the reverse mapping will only produce the specific numeric keys and string values seen in the forward mapping, but for some reason it's not implemented like that:
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
.
So the tightest constraint I can put on an enum type is the above E extends Enum<E>
.
请注意,此代码不适用于在运行时实际上不存在的 const enum
类型:
Note that this code does not work for const enum
types which don't really exist at runtime:
const enum F {U, V, W};
acceptEnum(F); // nope, can't refer to `F` by itself
还要注意上面的类型(E extends Enum
)允许一些它可能不应该做的事情:
And also note that the above type (E extends Enum<E>
) allows some things it maybe shouldn't:
acceptEnum({ foo: 1 }); // works
在上面,{foo: 1}
似乎是一个类似于 enum Foo {foo = 1}
的数字枚举,但它没有反向映射,如果你依赖它,事情会在运行时爆炸.请注意, {foo: 1}
似乎没有索引签名,但它仍然匹配索引签名 隐式.除非您添加了一些明确的错误值,否则它不会失败:
In the above, {foo: 1}
is plausibly a numeric enum similar to enum Foo {foo = 1}
but it doesn't have the reverse mapping, and if you rely on that things will blow up at runtime. Note that {foo: 1}
doesn't seem to have an index signature but it still matches an index signature implicitly. It wouldn't fail to match unless you added some explicit bad value:
acceptEnum({foo: 1, 2: 3}); // error, prop '2' not compatible with index signature
但是这里没有什么可做的.正如我上面提到的,enum
类型的实现目前并没有尽可能多地限制数字键,因此在编译时似乎无法区分具有良好反向映射的枚举一无二.
But there's nothing to be done here. As I mentioned above, the implementation of enum
typing currently does not constrain the numeric keys as much as it can, so there seems to be no way at compile time to distinguish between an enum with a good reverse mapping and one without one.
希望有所帮助.祝你好运!
Hope that helps. Good luck!
这篇关于Typescript 中的枚举类型是什么?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!