指定枚举类型

时间:2018-03-01 09:09:00

标签: typescript enums

有枚举:

enum Foo {
    Bar, // should cause type error
    Baz = 'Baz'
}

是否可以为其指定类型以使其成为仅字符串枚举?

2 个答案:

答案 0 :(得分:2)

如果您愿意,可以执行以下操作:

创建一个函数,要求其输入只有string - 值属性:

const enforceStringEnum = <E extends Record<keyof E, string>>(e: E) => {};

然后,根据需要声明Foo

enum Foo {
  Bar, 
  Baz = 'Baz'
}

并以Foo作为输入调用该函数:

enforceStringEnum(Foo); // error!
// Type 'Foo.Bar' is not assignable to type 'string'.

这会在您收到有关Foo.Bar的消息时出错,您可以返回并修复以删除错误。

是的,您获得的错误不是Foo声明的本地错误,但它确实允许您将Foo保留为enum,而不是使用其他语言结构。是的,enforceStringEnum()在运行时具有(非常小的)效果。如果你想要根本没有运行时工件,那么它是可能的,但(在我看来)有点丑陋:

type EnforceStringEnum<E extends Record<keyof E, string>> = true;

enum Foo {
  Bar,
  Baz = 'Baz'
}

declare var fooWitness: EnforceStringEnum<typeof Foo>; // error! 
// Type 'Foo.Bar' is not assignable to type 'string'.

但它的工作方式相同。

编辑:或者,正如@estus提到的,你可以使用类型别名而不是变量声明:

type FooWitness = EnforceStringEnum<typeof Foo>; // error!
// Type 'Foo.Bar' is not assignable to type 'string'.

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

答案 1 :(得分:1)

如果你检查生成的枚举的JS代码,你会发现它等同于

enum Foo {
    Bar = 0, // should cause type error
    Baz = 'Baz'
}

但允许在TypeScript中创建此类枚举,请参阅Heterogeneous Enums

您还可以使用命名空间:

namespace Foo {
    export const Bar: string = "Foo";
    export const Baz: string = "Baz";
}

或具有静态字段的类:

class Foo {
    static Bar: string = "Foo";
    static Baz: string = "Baz";
}

第一个好处是Bar中只有BazFoo属性,没有别的。