为什么枚举和单选按钮是完美搭配?
\n想象一下:您正在用 TypeScript 编写一个表单。需要让用户从多个选项中选择一个——例如,难度级别、订单状态或性别。这些选项存储在哪里?您可以硬编码一个字符串数组,但这是一条死路。当选项增多时,您会感到困惑,如果业务逻辑发生变化,您将不得不在十个地方修改代码。
\n这时,枚举(enum) 就登场了。它们允许您定义一组命名常量,既便于人类阅读,也能被机器理解。而单选按钮则是从列表中选择单个值的经典 UI 元素。将两者结合,意味着获得干净、可维护的代码。听起来很棒,但有一个问题:如何遍历枚举以在模板中显示它?这正是成千上万的开发者在 Stack Overflow 上纠结的问题。让我们一劳永逸地解决它。
\n\n问题:枚举不是数组
\n在 TypeScript 中,枚举不仅仅是一个字符串列表。根据您声明它的方式(数值型或字符串型),它的行为也不同。数值型枚举会创建反向映射:键 -> 值和值 -> 键。字符串型枚举则只有正向映射。因此,简单地写 for (let item in MyEnum) 是个坏主意。您不仅会得到所需的键,还会得到多余的反向映射。
下面是一个典型的陷阱:
\nenum Status {\n Active = 1,\n Inactive = 2,\n Pending = 3\n}\n\n// 不要这样做\nfor (let key in Status) {\n console.log(key); // "1", "2", "3", "Active", "Inactive", "Pending"\n}\n\n看到了吗?控制台输出了名称和值。如果您尝试将其显示为单选按钮,用户会看到难以理解的数字。这不符合我们的需求。
\n\n解决方案 #1:对字符串枚举使用 Object.values()
\n最简单且最可靠的方法是使用 Object.values()。此方法返回对象可枚举属性的值数组。对于字符串枚举,它完美工作,因为它们(几乎总是)没有反向映射。
示例:订单状态
\nenum OrderStatus {\n New = 'new',\n Processing = 'processing',\n Shipped = 'shipped',\n Delivered = 'delivered',\n Cancelled = 'cancelled'\n}\n\n// 获取值数组\nconst statusValues = Object.values(OrderStatus);\n// ['new', 'processing', 'shipped', 'delivered', 'cancelled']\n\n// 现在可以轻松在模板中显示(React)\nfunction StatusSelector() {\n return (\n <div>\n {statusValues.map((status) => (\n <label key={status}>\n <input type="radio" name="status" value={status} />\n {status}\n </label>\n ))}\n </div>\n );\n}\n\n一切简单而巧妙。我们得到了一个字符串数组,然后直接遍历它。适用于 React、Angular、Vue 等任何框架。
\n\n解决方案 #2:对数值枚举使用 Object.keys() + 过滤
\n对于数值枚举,情况更复杂一些。Object.values() 不仅会返回字符串键,还会返回数值,因为 JavaScript 将它们视为对象的“属性”。我们需要只过滤出字符串(键)。
示例:访问级别
\nenum AccessLevel {\n Guest = 0,\n User = 1,\n Moderator = 2,\n Admin = 3\n}\n\n// 过滤:只保留字符串(键)\nconst levelKeys = Object.keys(AccessLevel).filter(key => isNaN(Number(key)));\n// ['Guest', 'User', 'Moderator', 'Admin']\n\n// 如果需要获取对象数组以便于显示\nconst levelOptions = levelKeys.map(key => ({\n label: key,\n value: AccessLevel[key as keyof typeof AccessLevel]\n}));\n// [\n// { label: 'Guest', value: 0 },\n// { label: 'User', value: 1 },\n// ...\n// ]\n\n现在您有了一个选项数组,其中 label 是人类可读的名称,而 value 是便于