Typescript 的枚举可能不是你想象的那样

2023-11-29 21:45:04 浏览数 (1)

如果你对枚举(enum)的外观不熟悉,这里有一些示例:

代码语言:typescript复制
enum Direction {
  Up = 1,
  Down, // 2
  Left, // 3
  Right, // 4
}

参考资料:

代码语言:txt复制
<p>
    <a href="https://www.typescriptlang.org/docs/handbook/enums.html#reverse-mappings">枚举 - TypeScript手册</a>
</p>

枚举作为常量的集合。这可能会很有用,尤其是当你想要具有非常独特的键时:

代码语言:typescript复制
enum DirectiveKeys {
    Skip = '__c_skip_me_',
    Remove = '__c_remove_me_',
    Add = '__c_add_me_'
}

const objectThatShouldBeSkipped = {
    action: DirectiveKeys.Skip
}

使用它们的原因:

当使用枚举时,它锁定了常量,并将其保持在可管理的对象格式中:

代码语言:typescript复制
const DirectiveKeys = {
    Skip: '__c_skip_me_',
    Remove: '__c_remove_me_',
    Add: '__c_add_me_'
}

DirectiveKeys.Skip = '哎呀,这仍然是可变的';

const objectThatShouldBeSkipped = {
    action: DirectiveKeys.Skip // 永远不会被跳过
}

当使用枚举时,你还可以具有隐含的值:

代码语言:typescript复制
enum ExplicitValues {
    Up = 0,
    Down = 1,
    Right = 2,
    Left = 3
}

与下面的写法相同:

代码语言:typescript复制
enum ImplicitValues {
    Up,
    Down,
    Right,
    Left
}

不使用它们的原因:

它们没有被抽象化。没错,TypeScript 的枚举被编译进你的代码。你可能会说:“算了,反正是 TypeScript,它们知道自己在做什么。” 但他们所做的是将这个:

代码语言:typescript复制
enum Const {
    Up,
    Down,
    Right,
    Left
}

转换成这样:

代码语言:typescript复制
var Const;
(function (Const) {
    Const[Const["Up"] = 0] = "Up";
    Const[Const["Down"] = 1] = "Down";
    Const[Const["Right"] = 2] = "Right";
    Const[Const["Left"] = 3] = "Left";
})(Const || (Const = {}));

作为一个喜欢小型软件包的人,这是一段非常令人沮丧的代码。将枚举转换为对象/常量可以节省数百字节。为什么?

对于每个枚举,都有类似上面的 JavaScript 片段进行匹配。

生成的 JavaScript 只有在存在 TypeScript 时才能防止突变。否则它可以很容易地被覆盖,这是枚举类型的一个主要卖点。

这是使用 Proxy 生成枚举的原始方法:

代码语言:typescript复制
const Enum = (enums) => {
    Object.entries(enums).forEach((enums, [ key, value ]) => {
        enums[value] = key;
        return enums;
    })
    return new Proxy(enums, {
        get(target, key) {
            return target[key];
        },
        removeProperty: () => false,
        set: () => false,
    })
}

这禁止了添加或删除属性的能力,同时生成了 TypeScript 枚举生成的交替键值。

另一个好处?它是可重用的,并且不会创建相同代码的多个副本!

代码语言:typescript复制
const Directions = Enum({
    Up: 1,
    Down: 2,
    Right: 3,
    Left: 4
});

const Compass = Enum([
    "North",
    "East",
    "South",
    "West"
]);

哇,对于任何人来说都可以使用的生产就绪代码,太棒了!

现在等一下。

我的代码片段与 TypeScript 生成的代码的区别在于,我的代码利用了 ES6 的功能,比如 Proxy。如果你的目标受众不包括这个,那我只能说抱歉。

我的代码片段也没有 Microsoft 和 TypeScript 团队的支持,这意味着它没有经过充分的测试。

使用 TypeScript 枚举的最终和最重要的原因是?它们具有所有的智能提示优势。也许有一天我会为我的小函数开发一个相同的智能提示类型。

在那之前,随便你怎么做吧。

附言:

我认为生成的代码可能需要稍微更新一下。比如,使用箭头函数应该没问题。

代码语言:typescript复制
var Const;
((Const) => {
    Const[Const["Up"] = 0] = "Up";
    Const[Const["Down"] = 1] = "Down";
    Const[Const["Right"] = 2] = "Right";
    Const[Const["Left"] = 3] = "Left";
})(Const || (Const = {}));

我正在参与2023腾讯技术创作特训营第三期有奖征文,组队打卡瓜分大奖!

0 人点赞