Typescript 中的枚举类型是啥?

Posted

技术标签:

【中文标题】Typescript 中的枚举类型是啥?【英文标题】:What is the type of an enum in Typescript?Typescript 中的枚举类型是什么? 【发布时间】:2018-10-13 22:59:55 【问题描述】:

给定一个参数应该是enum 的函数。传入的enum 可以有不同数量的属性。如何修复该参数的类型? enum 本身不是一个类型。

例如:

function (myEnum: mysteriousType)
  //What is that mysteriousType ?


用例是构建一个通用方法来从枚举实例化dat.GUI 选项,无论枚举中的字符串/数字类型是什么。

【问题讨论】:

你read about enums in Typescript了吗? 您的意思是如何声明一个函数,该函数接受任何枚举的 any 值,或者将枚举作为对象?我的意思是,给定enum myEnum one, two, three ,你会如何调用你的函数? fn(myEnum)?或fn(myEnum.one)? @OscarPaz fn(myEnum)。但这也应该适用于fn(anyOtherRandomEnum) 您希望它仅适用于数字枚举还是字符串枚举?还是混合的? @crashmstr 似乎我没有读过那部分。如果我们首先定义数字和字符串枚举的类型,“运行时的枚举”段落应该回答这个问题。 【参考方案1】:

根据您的用例,这可能有效:(这是我使用的)

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[]

编辑:在重新阅读您的问题时,这似乎不是您想要的。将其保留在这里以供参考,因为它对于需要能够返回传入的给定枚举的“实例”的函数很有用(并且您不想手动提供括号中的类型)。

【讨论】:

这不适用于严格模式:( 虽然如此:github.com/microsoft/TypeScript/issues/…【参考方案2】:

到目前为止你所说的(需要接受所有字符串/数字/异构枚举),我能做的最接近的是这样的:

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&lt;E&gt;


请注意,此代码不适用于 const enum 在运行时不存在的类型:

const enum F U, V, W;
acceptEnum(F); // nope, can't refer to `F` by itself

还要注意,上述类型 (E extends Enum&lt;E&gt;) 允许一些它可能不应该做的事情:

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 键入的实现目前并没有尽可能多地限制数字键,因此在编译时似乎没有办法区分具有良好反向映射的枚举和没有的枚举。


希望对您有所帮助。祝你好运!

【讨论】:

感谢您提供详细而快速的答复和彻底的调查。暂时标记为正确。我很惊讶没有简单的方法,因为枚举对象本身并不容易处理。用例是一个循环遍历枚举属性的函数,这已经足够棘手了,在这个用例中,只会传入enum 你能发布一个例子,在接口中使用 emum 作为泛型类型吗? 你能解释一下 ` & [k: number]: string ;` 部分的作用吗? 我不明白你的第一个问题......我不是想以这种方式使用枚举的人,所以我不确定这个例子应该是什么。至于第二个问题,它意味着Enum&lt;E&gt; 应该有数值为字符串的数字键,以表示枚举的反向映射。 type Enum&lt;E&gt; = Record&lt;keyof E, number | string&gt; &amp; [k: number]: keyof E 可以更加精确,但差别不大

以上是关于Typescript 中的枚举类型是啥?的主要内容,如果未能解决你的问题,请参考以下文章

java中的枚举类型指的是啥啊?

VHDL 中的“std_logic”枚举类型的目的是啥?

枚举类型enum用法 c语言switch的用法是啥

带有接口的Typescript中的Json枚举?

java中的枚举是啥意思?

java中的枚举是啥意思?