将一个枚举转换为另一个枚举

时间:2021-03-30 11:24:54

标签: typescript enums

有没有办法在 Typescript 中转换枚举? 例如。我有一个原始枚举

enum original {
  VALUE_1
  VALUE_2
}

我想将大写转换为小写,如

enum original {
  value_1
  value_2
}

有可能吗?

1 个答案:

答案 0 :(得分:1)

一般来说,你可以写一个名为lowercaseKeys()的函数将任何对象的key转换为小写,然后assert这样的函数返回一个强类型的结果。返回类型涉及 key remapping 以创建映射类型,其中字符串 literal 通过 Lowercase intrinsic string manipulation type 键转换为小写对应项:

function lowercaseKeys<T extends object>(obj: T): { 
  [K in keyof T as K extends string ? Lowercase<K> : K]: T[K] 
} {
    return Object.fromEntries(
      Object.entries(obj).map(([k, v]) => [k.toLowerCase(), v])
    ) as any;
}

同样,这应该适用于任何对象:

const example = lowercaseKeys({ STR: "hello", NUM: Math.PI });
/* const example: {
    str: string;
    num: number;
} */
console.log(example.num.toFixed(2)); // 3.14

您可以看到,在运行时,example 具有名为 strnum 的键,并且编译器知道这一点。


enum 也是一个具有键和值的对象,所以你可以用同样的方式转换它:

const LowercaseEnum = lowercaseKeys(OriginalEnum);
/* const LowercaseEnum: {
    [x: number]: string;
    readonly value_1: OriginalEnum.VALUE_1;
    readonly value_2: OriginalEnum.VALUE_2;
} */
console.log(LowercaseEnum.value_1.toFixed()); // "0"
console.log(LowercaseEnum.value_2.toFixed()); // "1"

万岁!


嗯,就目前而言,这很棒。但请注意,enum 除了常规对象外还具有一些特殊功能。 (有关这种差异的更深入描述,请参见 this answer。)例如,enum 的名称也可以用作与它的价值:

interface Okay {
    e: OriginalEnum;
}

但是 LowercaseEnum 只是一个对象,并没有声明为 enum;没有名为 LowercaseEnum 的类型:

interface Oops {
    e: LowercaseEnum; // error
    // ~~~~~~~~~~~~~
    // 'LowercaseEnum' refers to a value, 
    // but is being used as a type here.
}

如果你想要这样的类型,你必须做到:

type LowercaseEnum = OriginalEnum; // same values, so same type

另一个区别是像enum这样的真数字OriginalEnum有一个reverse mapping,如果OriginalEnum.VALUE_10,那么OriginalEnum[0]"VALUE_1"

console.log(OriginalEnum[0]); // "VALUE_1" as expected

但是转换后的版本没有有用的反向映射,因为只有它的键被改变了;它的价值不变:

console.log(LowercaseEnum[0]); // still "VALUE_1", unexpected?

因此,使用 LowercaseEnum 之类的内容时请小心:虽然有相似之处,但它不是真正的 enum


Playground link to code