将一个枚举的键引用到另一个枚举的键或值

时间:2020-07-14 02:32:43

标签: typescript enums

在下面的代码中,PropertiesNamesInDataBase的键必须与User.Keys相同。 显然,PropertiesNamesInDataBase的值正在后端使用,但前端的名称必须统一。

namespace User {
    export enum Keys {
        ID = "ID",
        name = "name"
    }
}

enum PropertiesNamesInDataBase {
    ID = "id",
    name = "nm"
}

这里至少有两个问题:

  1. 我们需要重新输入密钥或将其复制粘贴
  2. PropertiesNamesInDataBase完全独立于User.Keys,但是从概念上讲PropertiesNamesInDataBase的键必须以某种方式引用User.Keys

这里尝试通过将PropertiesNamesInDataBase键引用到User.Keys来解决第二个问题:

namespace User {
    export enum Keys {
        ID = "ID",
        name = "name"
    }
}

enum PropertiesNamesInDataBase {
    [User.Keys.ID] = "id",
    [User.Keys.name] = "nm"
}

但是在TypeScript中是不可能的:

Computed property names are not allowed in enums. (1164)

请告诉我如何重用枚举键,或如何在PropertiesNamesInDataBase的值上引用User.Keys的键。

1 个答案:

答案 0 :(得分:1)

我倾向于完全忘记enum,而是建立自己的枚举式对象。这将为您提供只需要编写一次密钥的灵活性,但是您将失去enum附带的一些内置表达能力(即enum Foo {...}会创建两个 object < / em>命名为Foo type 命名为Foo。如果您创建const Foo = ...,则只会得到 object ,如果需要的话,您需要自己定义自己的类型)。

这是一种方法:

const KeysAndPropNames = {
  ID: { key: "ID", propName: "id" },
  name: { key: "name", propName: "nm" }
} as const;

您只有一个对象,它是从键到您在旧User.KeysPropertiesNamesInDataBase枚举中的值的映射。您可以这样自己提取那些类似于枚举的对象:

const User = { Keys: objMapProp(KeysAndPropNames, "key") };
const PropertiesNamesInDataBase = objMapProp(KeysAndPropNames, "propName");

其中objMapProp()是一个函数,您可以将其放置在库中,该函数将对象的属性访问映射到该对象:

// library
function objMapProp<T extends Record<keyof T, Record<K, any>>, K extends keyof any>(
  obj: T,
  key: K
) {
  const ret = {} as { [P in keyof T]: T[P][K] };
  for (let k in obj) {
    ret[k] = obj[k][key];
  }
  return ret;
}

如果您使用IntelliSense检查新的UserPropertiesNamesInDataBase对象的类型,您会发现它们与旧值匹配:

/* const User: {
    Keys: {
        readonly ID: "ID";
        readonly name: "name";
    };
} */

/* const PropertiesNamesInDataBase: {
    readonly ID: "id";
    readonly name: "nm";
} */

如果要使用名为User.KeysPropertiesNamesInDataBase类型,可以将它们作为对应对象的所有值类型的并集:

namespace User {
  export type Keys = (typeof User.Keys)[keyof typeof User.Keys];
  // type User.Keys = "ID" | "name"
}
type PropertiesNamesInDataBase = typeof PropertiesNamesInDataBase[keyof typeof PropertiesNamesInDataBase];
// type PropertiesNamesInDataBase = "id" | "nm"

无论如何,希望能满足您的需求或使您知道如何进行。祝你好运!

Playground link to code