【问题标题】:How can I declare an Enum in TypeScript that will map to environment-defined global properties?如何在 TypeScript 中声明一个将映射到环境定义的全局属性的枚举?
【发布时间】:2018-01-01 22:20:26
【问题描述】:

我有一个全局包含多个常量的环境:

TOP = 1
TOP_RIGHT = 2
RIGHT = 3
BOTTOM_RIGHT = 4
BOTTOM = 5
BOTTOM_LEFT = 6
LEFT = 7
TOP_LEFT = 8

我很清楚,这 8 个常量不仅仅是任意常量,实际上是一组方向。因此,我想让它们成为DIRECTION 类型,这样我就可以做这样的事情:

let test: DIRECTION = TOP_LEFT;

enum 类型似乎是实现这一点最合乎逻辑的方式,但我遇到了以下问题:


我之前尝试过实现这种行为,但遇到了一些困难。

src/main.ts(1,23): error TS2304: Cannot find name 'TOP_LEFT'.

打字稿文件:

main.ts:

let test: DIRECTION = TOP_LEFT;
console.log(test);

direction.d.ts:

declare enum DIRECTION {
    TOP = 1,
    TOP_RIGHT = 2,
    RIGHT = 3,
    BOTTOM_RIGHT = 4,
    BOTTOM = 5,
    BOTTOM_LEFT = 6,
    LEFT = 7,
    TOP_LEFT = 8,
}

忽略编译错误,运行“tsc”(也称为转译代码)的 JavaScript 结果看起来它将访问预定义的全局属性:

let test = TOP_LEFT;
console.log(test);

如何以对 TypeScript 友好的方式获得这样的输出?

【问题讨论】:

    标签: javascript typescript enums


    【解决方案1】:

    您错误地解释了枚举的使用。枚举在 Javascript 中的存在方式与例如 c++ 不同。当编译器编译您的枚举声明时,会在其位置创建一个新变量,其中包含用于检索键和值的映射。

    以下枚举...

    enum Example {
        One,
        Two
    }
    

    ...是以下 Javascript 对象的 TypeScript 等效项:

    var Example;
    (function (Example) {
        Example[Example["One"] = 0] = "One";
        Example[Example["Two"] = 1] = "Two";
    })(Example || (Example = {}));
    

    您似乎想要的是一组映射到一种类型的常量。你可以在 TypeScript 中声明文字类型。例如declare type Direction = 1 | 2 | 3 ... | 8;。但是,当您重构代码或添加更多方向常量时,这并不是真正有用。幸运的是,您可以使用 typeof 关键字来获取对象的值。您可以按如下方式声明您的 Directions 类型:

    const TOP = 1
    const TOP_RIGHT = 2
    const RIGHT = 3
    const BOTTOM_RIGHT = 4
    const BOTTOM = 5
    const BOTTOM_LEFT = 6
    const LEFT = 7
    const TOP_LEFT = 8
    
    declare type Direction =
        typeof TOP |
        typeof TOP_RIGHT |
        typeof RIGHT |
        typeof BOTTOM_RIGHT |
        typeof BOTTOM |
        typeof BOTTOM_LEFT |
        typeof LEFT |
        typeof TOP_LEFT;
    
    const dir: Direction = TOP_LEFT; // or = 8
    

    使用这种Direction 类型声明的变量必须具有与该类型匹配的值,例如在你的情况下 1 到 8。

    但是,我宁愿使用枚举而不是声明一堆全局变量。

    【讨论】:

      【解决方案2】:

      您已经声明了一个环境枚举:enums。它们通常用于为预先存在的类型提供类型信息 - 例如。一个在导入的 js 库中定义。如果您查看转译的代码,您会发现它没有 实际上发出了任何类型的查找。

      声明枚举的正常方式是:

       enum DIRECTION {
          TOP = 1,
          TOP_RIGHT = 2,
          RIGHT = 3,
          BOTTOM_RIGHT = 4,
          BOTTOM = 5,
          BOTTOM_LEFT = 6,
          LEFT = 7,
          TOP_LEFT = 8,
      }
      

      会产生:

      var DIRECTION;
      (function (DIRECTION) {
          DIRECTION[DIRECTION["TOP"] = 1] = "TOP";
          DIRECTION[DIRECTION["TOP_RIGHT"] = 2] = "TOP_RIGHT";
          DIRECTION[DIRECTION["RIGHT"] = 3] = "RIGHT";
          DIRECTION[DIRECTION["BOTTOM_RIGHT"] = 4] = "BOTTOM_RIGHT";
          DIRECTION[DIRECTION["BOTTOM"] = 5] = "BOTTOM";
          DIRECTION[DIRECTION["BOTTOM_LEFT"] = 6] = "BOTTOM_LEFT";
          DIRECTION[DIRECTION["LEFT"] = 7] = "LEFT";
          DIRECTION[DIRECTION["TOP_LEFT"] = 8] = "TOP_LEFT";
      })(DIRECTION || (DIRECTION = {}));
      

      然后你会像这样使用它:

      const t: DIRECTION = DIRECTION.TOP_LEFT;
      

      【讨论】:

      • 如果我不想使用DIRECTION.TOP_LEFT 而是使用TOP_LEFT 访问它怎么办?
      • 那么就声明一堆consts
      猜你喜欢
      • 2020-09-16
      • 1970-01-01
      • 2019-07-05
      • 2018-03-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多