从一个联合类型中创建一个 TypeScript (字符串) 枚举?

8
如果我有一个TypeScript联合类型,像这样:
type SomeUnion = 'Foo' | 'Bar' | 'Baz';

有没有办法将这个转换为基于字符串的枚举?像下面这样:

enum SomeUnionBasedEnum {
  Foo = 'Foo',
  Bar = 'Bar',
  Baz = 'Baz'
}

我正在尝试建模一个枚举,代表我们系统中的权限,但这些权限在某些情况下是自动生成的联合类型。我希望有一种方法将它们组合成一个单一的枚举,因为枚举通过限制智能感知的可允许值提供更好的开发者体验。例如AppPermisionEnum.<可用的枚举值>。我也可以接受将枚举合并成一个单一的枚举的方式,但我认为这是不可能的。我的最终目标是创建一个由几个不同来源的值组成的枚举。


2
但是字符串字面类型已经提供了智能感知。如果您在期望字符串字面值的位置键入“”,则会获得有关可能值的智能感知... - Titian Cernicova-Dragomir
1个回答

8

就像我在评论中指出的那样,字符串字面量类型已经提供了良好的智能感知支持,所以我个人会只使用它们而不去创建其他东西,开发体验已经很好了。

下面的代码是在寻找问题的解决方案,但我们可以做一些接近你想要的东西。

你不能创建一个枚举,但你可以创建一个对象,该对象具有联合类型的所有属性,并且每个属性都具有与键相同的值,使用映射类型。你需要手动维护这些对象,但如果它们不同步,TypeScript 将会发出警告,因此维护它们不应该成为问题。

type SomeUnion = 'Foo' | 'Bar' | 'Baz';

function createEnumObject<T extends string>(o: { [P in T]: P }) {
    return o;
}

const SomeUnion = createEnumObject<SomeUnion>({
    Foo: "Foo",
    Bar: "Bar",
    Baz: "Baz"
})

let o: SomeUnion = SomeUnion.Bar;

在不使用额外代码的情况下将一个联合类型(即一种类型)转换为一个对象(即一个值)原则上是不可能的,因为类型在编译时被擦除,所以不能在运行时依赖于它们,并且TypeScript有一个严格的类型导向发射策略。


1
联合类型很好,但我正在考虑创建一个枚举类型,主要是为了可维护性,以防需要重命名字符串。在代码库中可能会多次使用字符串字面量“apple”,但使用枚举可以轻松地重命名事物,而全局字符串查找和替换则会失败。 - mxiong
@mxiong 枚举类型确实有其优点。虽然重命名可能无法正常工作,但在使用旧版本字符串的任何地方都应该会出现错误。 - Titian Cernicova-Dragomir

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接