不要在 Typescript 中使用枚举,它们非常危险😨

2025-06-07

不要在 Typescript 中使用枚举,它们非常危险😨

你有没有想过为什么 TypeScript 专家建议避免使用 ENUM?虽然它们看起来像是定义一组常量值的有用工具,但实际上非常危险。在本文中,我们将向你展示为什么以及如何避免使用它们。你会发现有很多更安全可靠的替代方案可供选择。准备好迎接惊喜吧!😱

枚举的发射代码

建议不要使用它的原因之一是,它在编译应用程序时会生成代码。ENUM 会在编译时生成额外的代码,这会增加最终文件的大小。这可能会对应用程序的加载速度和性能产生负面影响。

定义我们的角色枚举

enum Roles {
  Admin,
  Writer,
  Reader
}
Enter fullscreen mode Exit fullscreen mode

输出(构建生成的代码)

var Roles;
(function (Roles) {
    Roles[Roles["Admin"] = 0] = "Admin";
    Roles[Roles["Writer"] = 1] = "Writer";
    Roles[Roles["Reader"] = 2] = "Reader";
})(Roles|| (Roles = {}));
Enter fullscreen mode Exit fullscreen mode

虽然如果使用常量枚举,这个细节确实是固定的,但我参与过多个项目,看到人们到处使用常规枚举,并想知道为什么他们的输出如此之大。

Postada:我曾经也是其中之一。😁

这看起来可能微不足道,但想象一下,如果您在“前端”和“后端”之间共享文件,您最终可能会得到相当重的捆绑包。

好的,这是一方面,我们可以通过强制使用常量来解决这个问题。但这也带来了令人不快的歧义。

数字类型usafe

是的,你没看错。这不是标题党。常规的数字枚举(例如不设置字符串值的枚举)并非类型安全!如果我们回顾一下之前的 Roles 枚举,就会发现接受用户角色的函数实际上也可以接受任意数字值。

enum Roles {
  Admin,
  Writer,
  Reader
}

declare function hasAccess(role: Roles): void;

hasAccess(10);
// ☝️ Worst of all, this is ok! 😱
Enter fullscreen mode Exit fullscreen mode

您可能已经注意到,当hasAccess(10)调用该函数时,传递的数值不属于枚举 Roles,这在 TypeScript 中是允许的,而这被视为问题,因为它允许输入意外和未经验证的值,这可能会导致应用程序出现安全和性能问题。

字符串 ENUM 是命名类型

在结构类型盛行的时代,枚举类型选择成为命名类型。这意味着,即使值有效且受支持,它们也无法传递给需要字符串枚举的函数或对象。让我们看这个例子:

enum Roles {
  Admin = 'admin',
  Writer = 'writer',
  Reader = 'reader'
}

declare function hasAccess(role: Roles): void;

hasAccess('admin') // Invalid.
hasAccess(Roles.Admin) // Valid.
Enter fullscreen mode Exit fullscreen mode

如您所见,枚举是一种命名类型,并且仅接受特定于枚举的值,而不是兼容或相似的值,这可能导致兼容性问题,在设计和使用枚举时应仔细考虑。

解决方案

一个更安全、更能保证兼容性的替代方案是使用对象。让我们看下面的例子:

const Roles = {
  Admin: "admin",
  Writer: "writer",
  Reader: "reader"
} as const;

// Convert object key in a type
type RoleKeys = typeof Roles[keyof typeof Roles]

declare function hasAccess(role: RoleKeys): void;

// 💥 Error!
move('guest');

// 👍 Great!
move('admin');

// 👍 Also great!
move(Roles.Admin);
Enter fullscreen mode Exit fullscreen mode

结论

枚举 (ENUM) 看似是一个定义常量值的有用工具,但实际上却非常危险。过度使用常规枚举可能会导致代码大小问题、安全性问题、可扩展性和可维护性问题。

与其使用枚举,不如选择对象或类型。对象灵活且可扩展,这意味着它们可以在运行时修改并添加新值。类型也同样灵活且可扩展,并且能够提供更好的代码清晰度和可读性。此外,与枚举相比,对象和类型更不容易出现错误和安全问题。简而言之,就灵活性、可扩展性、清晰度、可读性和安全性而言,使用对象或类型代替枚举是更好的选择。

关注我❤️

文章来源:https://dev.to/ivanzm123/dont-use-enums-in-typescript-they-are-very-dangerous-57bh
PREV
彻底学会使用装饰器
NEXT
使用 Plop.js 以光速创建 React 组件