【发布时间】:2018-03-01 09:09:00
【问题描述】:
有枚举:
enum Foo {
Bar, // should cause type error
Baz = 'Baz'
}
是否可以为其指定类型以使其成为纯字符串枚举?
【问题讨论】:
标签: typescript enums
有枚举:
enum Foo {
Bar, // should cause type error
Baz = 'Baz'
}
是否可以为其指定类型以使其成为纯字符串枚举?
【问题讨论】:
标签: typescript enums
如果需要,您可以执行以下操作:
创建一个要求其输入仅具有string-valued 属性的函数:
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'.
希望对您有所帮助。祝你好运!
【讨论】:
declare 命名空间污染,我认为单独使用类型进行类型检查可以更好地达到目的。如果您知道如何以更好的方式解决this,我将不胜感激。
declare var 或 type)都会将不必要的名称添加到命名空间(值或类型),因此由您决定要执行哪个名称。类型更干净,但您可以多次重新声明相同的var(只要类型相同),这样您就可以减少对命名空间的污染。
如果你检查为你的枚举生成的 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";
}
第一个好处是Foo中只有Bar和Baz属性,没有别的。
【讨论】:
Bar 或 Bar = 0 应该会导致类型错误。
type Foo = "Bar" | "Baz"?这样您甚至不需要使用前缀Foo 并直接发送"Bar" 和"Baz"。
type Foo,但我的意图是摆脱原始字符串,因为Baz 属性值可以是一个长字符串。