将整数值转换为打字稿中的字符串枚举 returns 未定义

Casting integer value to String Enum in typescript returns undefined

我的 API returns 字符串枚举。所以我已经注册了我的枚举。

export enum MyEnum {
    Unknown = 'Unknown',
    SomeValue = 'SomeValue',
    SomeOtherValue = 'SomeOtherValue',
  }

现在我们从另一个来源获得了一个我们无法更改的整数值。这需要在某个时候映射到 MyEnum 并检查条件。使用下面的代码应该可以工作,但由于某些原因 returns 未定义。

const myIntValue = 1;
const myEnumValue = MyEnum[myIntValue]; // This returns undefined..

var myCondition = myEnumValue === MyEnum.SomeValue; // Is false because undefined != MyEnum.SomeValue

如何让打字稿中的枚举值转换为正确的枚举值或至少适用于我的条件?

你有两个选择。

第一个,你可以修改你的enum

enum MyEnum {
    Unknown = 1,
    SomeValue,
    SomeOtherValue,
}

const myIntValue = 1;
const myEnumValue = MyEnum[myIntValue]; // string

如果您从 MyEnum 定义中删除 1,它将从 0.

开始

就我个人而言,我不喜欢这个解决方案,因为 numerical enum 不是最佳选择。

考虑这个例子:

const foo = (en: MyEnum) => 42

foo(99999) // ok

第二个选项。

您可以使用元组将整数映射到枚举:

const enum MyEnum {
    Unknown = 'Unknown',
    SomeValue = 'SomeValue',
    SomeOtherValue = 'SomeOtherValue',
}

const MapEnum = [MyEnum.Unknown, MyEnum.SomeValue, MyEnum.SomeOtherValue] as const;

const result = MapEnum[1] // MyEnum.SomeValue

请记住,enum/object 键是无序的,因此动态创建这样的元组是不安全的。

更新

Second option works although it is more error prone ...

enum MyEnum {
    Unknown = 'Unknown',
    SomeValue = 'SomeValue',
    SomeOtherValue = 'SomeOtherValue',
}

type TupleUnion<U extends string, R extends any[] = []> = {
    [S in U]: Exclude<U, S> extends never ? [...R, S] : TupleUnion<Exclude<U, S>, [...R, S]>;
}[U];

const MapEnum: TupleUnion<MyEnum> = [MyEnum.Unknown, MyEnum.SomeValue, MyEnum.SomeOtherValue,];

你绝不会忘记一些值

没有排列的替代方法:

enum MyEnum {
    Unknown = 'Unknown',
    SomeValue = 'SomeValue',
    SomeOtherValue = 'SomeOtherValue',
}

// credits goes to 
type UnionToIntersection<U> = (U extends any ? (k: U) => void : never) extends (
    k: infer I
) => void
    ? I
    : never;

// Credits goes to https://github.com/microsoft/TypeScript/issues/13298#issuecomment-468114901
type UnionToOvlds<U> = UnionToIntersection<
    U extends any ? (f: U) => void : never
>;

type PopUnion<U> = UnionToOvlds<U> extends (a: infer A) => void ? A : never;

type IsUnion<T> = [T] extends [UnionToIntersection<T>] ? false : true;

type UnionToArray<T, A extends unknown[] = []> = IsUnion<T> extends true
    ? UnionToArray<Exclude<T, PopUnion<T>>, [PopUnion<T>, ...A]>
    : [T, ...A];

type Result = UnionToArray<MyEnum>

const MapEnum: UnionToArray<MyEnum> = [MyEnum.Unknown, MyEnum.SomeValue, MyEnum.SomeOtherValue,];

您可以在我的 blog

中找到更多示例