TypeScript类中的常量:从新手到专家
\n\n你是否曾经在编写TypeScript时突然意识到:“这个神奇的字符串“ADMIN”我在十个地方都用到了,如果拼写错误,编译器却不会报错”?熟悉的痛点。或者更糟的是,团队中有人直接在运行时修改了常量的值,而你花了一个小时调试才明白为什么一切都崩溃了。
\n\n欢迎来到TypeScript类常量的世界。这不仅仅是语法糖——它是构建干净、可预测且安全架构的基础。在本文中,我们将探讨在TypeScript类中声明常量的所有方法:从简单的readonly到使用as const和泛型的高级技巧。开始吧!
为什么类中的常量很重要?
\n\n想象一下,你正在开发一个电商应用。你有一个Order类,其中包含状态:"pending"、"shipped"、"delivered"。如果你将这些字符串分散在代码各处,迟早会有人写成大写的"PENDING"——bug就来了。TypeScript类常量能一劳永逸地解决这个问题。
- \n
- 类型安全:编译器不会允许将"pendingg"传递给需要"pending"的地方。 \n
- 可读性:
OrderStatus.Pending比单纯的字符串更清晰。 \n - 可维护性:在一个地方修改值,所有地方都会更新。 \n
方法#1:readonly——基础但有细节
\n\n最简单的方法是使用readonly修饰符。它禁止在初始化后修改字段。
class AppConfig {\n readonly API_URL: string = 'https://api.example.com';\n readonly MAX_RETRIES: number = 3;\n}\n\nconst config = new AppConfig();\nconsole.log(config.API_URL); // 'https://api.example.com'\n// config.API_URL = 'new-url'; // 错误!无法分配到'API_URL',因为它是只读属性。\n\n但有一个陷阱:readonly仅在TypeScript层面生效。在编译后的JavaScript中,这些字段仍然可以被修改。要完全保护,请使用Object.freeze或#(私有字段)。
方法#2:static readonly——常量之王
\n\n如果常量不绑定到类的特定实例(99%的情况都是如此),请使用static readonly。这是经典的class constant typescript模式。
class MathConstants {\n static readonly PI: number = 3.14159;\n static readonly E: number = 2.71828;\n static readonly GOLDEN_RATIO: number = 1.61803;\n}\n\n// 无需创建实例即可访问\nconsole.log(MathConstants.PI); // 3.14159\n// MathConstants.PI = 3.14; // 错误!\n\n这种方法非常适合配置、数学常量、状态以及任何不应更改的值。
\n\n方法#3:enum——当常量很多时
\n\n如果你有一组相关的常量(例如订单状态),enum是你最好的朋友。它创建了一个命名值集合。
enum OrderStatus {\n Pending = 'pending',\n Shipped = 'shipped',\n Delivered = 'delivered',\n Cancelled = 'cancelled'\n}\n\nclass Order {\n constructor(public status: OrderStatus) {}\n}\n\nconst order = new Order(OrderStatus.Pending);\nconsole.log(order.status); // 'pending'\n\n// order.status = 'pendingg'; // 错误!类型'"pendingg"'不能赋值给类型'OrderStatus'\n\n提示:如果你使用字符串enum(如示例所示),它们在运行时提供可读的值。数字enum更快,但调试起来更困难。
方法#4:as const——追求最大严格性
\n\n有时你希望对象或数组成为常量