Typescript 指定枚举类型

Typescript 指定枚举类型,typescript,enums,Typescript,Enums,有两个枚举: enum Foo { Bar, // should cause type error Baz = 'Baz' } 是否可以为其指定一个类型,使其成为仅字符串枚举?如果检查生成的枚举JS代码,您将看到它与 enum Foo { Bar = 0, // should cause type error Baz = 'Baz' } 但允许在TypeScript中创建此类枚举,请参阅 您还可以使用命名空间: namespace Foo { expo

有两个枚举:

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

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

如果检查生成的枚举JS代码,您将看到它与

enum Foo {
    Bar = 0, // should cause type error
    Baz = 'Baz'
}
但允许在TypeScript中创建此类枚举,请参阅

您还可以使用命名空间:

namespace Foo {
    export const Bar: string = "Foo";
    export const Baz: string = "Baz";
}
或具有静态字段的类:

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

第一种方法的好处是,在
Foo
中只有
Bar
Baz
属性,没有其他属性。

如果需要,可以执行以下操作:

创建一个只要求其输入具有
字符串
值属性的函数:

const enforceStringEnum = <E extends Record<keyof E, string>>(e: E) => {};
并以
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'.
类型EnforceStringEnum=true;
enum Foo{
酒吧,
Baz='Baz'
}
声明var fooWitness:EnforceStringEnum;//错误!
//类型“Foo.Bar”不可分配给类型“string”。
但它的工作原理是一样的

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

type FooWitness = EnforceStringEnum<typeof Foo>; // error!
// Type 'Foo.Bar' is not assignable to type 'string'.
type FooWitness=EnforceStringEnum;//错误!
//类型“Foo.Bar”不可分配给类型“string”。

希望有帮助。祝你好运

没错。我正在寻找一种方法,以避免开发人员(我)在需要异类枚举的地方意外创建混合枚举。您所说的“在需要异类枚举的地方意外创建混合枚举”是什么意思?其目的是强制Foo成为仅字符串的枚举
Bar
Bar=0
应该会导致类型错误。我认为目前不可能,使用字符串文本联合类型如何,例如
type Foo=“Bar”|“Baz”
?这样,您甚至不需要使用前缀
Foo
并直接发送
“Bar”
“Baz”
。我将
键入Foo
,但我的目的是摆脱原始字符串,因为
Baz
属性值可能是一个长字符串。谢谢,最近刚刚有机会检查这个答案。这是一个非常巧妙的把戏。我担心
declare
namespace污染,我认为单独使用类型进行类型检查更能达到目的。如果您有更好的解决方法,我将不胜感激。alias witness类型也是一个好主意。无论哪种方式(
declare var
type
)都会在名称空间(值或类型)中添加不必要的名称,因此您可以选择哪个名称。类型比较干净,但是可以多次重新声明相同的
var
(只要类型相同),这样就可以减少对命名空间的污染。
type FooWitness = EnforceStringEnum<typeof Foo>; // error!
// Type 'Foo.Bar' is not assignable to type 'string'.