TypeScript - 数据类型详解4(字面量类型、枚举类型)
作者:hangge | 2026-08-03 08:45
在前面的文章中,我介绍了 TypeScript 的对象类型、联合类型和类型别名等高级类型。本文将继续深入探讨 TypeScript 类型系统的另外两个重要特性:字面量类型 和 枚举类型。字面量类型允许我们将类型精确限定为某个具体的值,非常适合用于约束变量的取值范围。枚举类型则是 TypeScript 独有的特性(不存在于 JavaScript 中),用于定义一组命名的常量。掌握这两种类型,可以让我们在开发中更好地表达业务逻辑,提高代码的可读性和可维护性。





一、字面量类型
1,基本概念
(1)在 TypeScript 中,除了常规的 string、number、boolean 等类型外,我们还可以使用 字面量类型(Literal Type),将类型精确限定为某个具体的值。
(2)下面是字面量类型的基本使用示例:
提示:字面量类型的变量只能被赋值为该字面量本身。单独使用字面量类型通常没有太大意义,但当我们将多个字面量类型联合在一起时,就能获得非常有用的结果。
// "Hello World" 也可以作为一种类型,叫作字面量类型 let message: "Hello World" = "Hello World"; // 错误:Type '"coder"' is not assignable to type '"Hello World"' // message = "coder"; // 只能赋值 "Hello World" // 123 也可以作为一种类型 let num: 123 = 123; // num = 456; // 错误:不能赋其他值
2,联合字面量类型
(1)字面量类型的真正价值在于与联合类型结合使用,形成 联合字面量类型,用于限制变量的取值范围:
提示:联合字面量类型非常适合用于表示有限的选项集合,如对齐方式、状态码、用户角色等场景。相比使用 string 类型,它能在编译时就发现拼写错误。
(2)在下面的代码中,Alignment 类型由多个字面量类型联合形成,限制了 align 变量只能取 'left'、'right' 或 'center' 这三个值之一。
// 将多个字面量类型联合在一起,限制 align 的取值范围 type Alignment = 'left' | 'right' | 'center'; let align: Alignment = 'left'; // 正常 align = 'right'; // 正常 align = 'center'; // 正常 // 错误:Type '"bottom"' is not assignable to type 'Alignment' // align = 'bottom';
3,字面量推理与 as const
(1)在实际开发中,TypeScript 会根据变量的声明方式自动推断类型。使用 const 声明的变量会被推断为具体的字面量类型,而不是宽泛的类型。
(2)但是,当对象属性需要作为字面量类型传递时,可能会遇到类型推断的问题。例如下面的代码报错是因为 options 对象进行自动类型推导时,推导出了 {url: string,method: string} 类型,无法将 string 类型赋值给字面量类型。
type Method = 'GET' | 'POST';
function request(url: string, method: Method) {
console.log(`请求 ${url},方法:${method}`);
}
const options = {
url: "https://www.example.com/api",
method: "POST"
};
// 错误:Argument of type 'string' is not assignable to parameter of type 'Method'
// request(options.url, options.method);
// 原因:options.method 被推断为 string 类型,而不是 'POST' 字面量类型
(3)我们可以使用以下三种方式来解决该问题:
提示:as const 断言会将对象或数组的所有属性变为只读的字面量类型,这是最简洁的解决方案。它不仅能解决类型推断问题,还能防止意外修改。
type Method = 'GET' | 'POST';
function request(url: string, method: Method) {
console.log(`请求 ${url},方法:${method}`);
}
// ========== 方式一:使用类型断言 as ==========
const options1 = {
url: "https://www.example.com/api",
method: "POST"
};
request(options1.url, options1.method as Method); // 正常
// ========== 方式二:为对象指定类型 ==========
type RequestOptions = {
url: string;
method: Method;
};
const options2: RequestOptions = {
url: "https://www.example.com/api",
method: "POST" // 这里必须是 GET 或 POST
};
request(options2.url, options2.method); // 正常
// ========== 方式三:使用 as const 断言(推荐)==========
const options3 = {
url: "https://www.example.com/api",
method: "POST"
} as const; // 将对象的所有属性变为字面量类型
request(options3.url, options3.method); // 正常二、枚举类型
1,认识枚举
(1)枚举(Enum) 是 TypeScript 独有的特性,不存在于 JavaScript 中。枚举用于将一组可能出现的值逐个列举出来,定义在一个类型中。
提示:枚举类型非常适合用于表示一组固定的选项,如方向、状态、颜色等。相比字面量联合类型,枚举提供了更好的代码组织和运行时支持。
(2)枚举类型使用 enum 关键字定义,下面代码使用 enum 关键字可以定义一个枚举类型,其中 LEFT 和 RIGHT 是该枚举的两个成员。调用函数时传入枚举成员,可以获得良好的类型检查。
// 定义 Direction 枚举
enum Direction {
LEFT,
RIGHT
}
// 指定 direction 参数为 Direction 枚举类型
function turnDirection(direction: Direction) {
switch (direction) {
case Direction.LEFT:
console.log("改变角色的方向向左");
break;
case Direction.RIGHT:
console.log("改变角色的方向向右");
break;
default:
// 使用 never 确保枚举的每个成员都被处理
const _check: never = direction;
break;
}
}
// 使用枚举:调用函数时传入对应的枚举项
turnDirection(Direction.LEFT); // 输出:改变角色的方向向左
turnDirection(Direction.RIGHT); // 输出:改变角色的方向向右

2,数字枚举
(1)枚举类型的成员默认是有值的。对于 数字枚举,如果没有指定值,默认从 0 开始自增长:
enum Direction {
LEFT, // 默认值为 0
RIGHT // 默认值为 1
}
// 获取枚举成员的值
console.log(Direction.LEFT); // 输出:0
console.log(Direction.RIGHT); // 输出:1

(2)我们也可以为枚举成员指定自定义的数值:
enum Direction {
LEFT = 100, // 指定值为 100
RIGHT // 自动递增,值为 101
}
console.log(Direction.LEFT); // 输出:100
console.log(Direction.RIGHT); // 输出:101

(3)数字枚举还有一个重要的特性:反向映射。既可以通过名称获取值,也可以通过值获取名称:
注意:反向映射只适用于 数字枚举,字符串枚举不支持反向映射。这是因为在编译后的代码中,数字枚举会生成双向映射对象,而字符串枚举只会生成单向映射。
enum Direction {
LEFT, // 0
RIGHT // 1
}
// 正向映射:名称 -> 值
console.log(Direction.LEFT); // 输出:0
console.log(Direction["LEFT"]); // 输出:0
// 反向映射:值 -> 名称
console.log(Direction[0]); // 输出:"LEFT"
console.log(Direction[1]); // 输出:"RIGHT"

3,字符串枚举
(1)除了数字枚举,TypeScript 还支持 字符串枚举。字符串枚举的每个成员都必须显式指定字符串值:
提示:字符串枚举在调试时更加友好,因为它的值本身就是有意义的字符串,而不需要根据数字去查找对应的名称。在需要语义清晰的场景下,推荐使用字符串枚举。
enum Direction {
LEFT = "LEFT",
RIGHT = "RIGHT"
}
console.log(Direction.LEFT); // 输出:"LEFT"
console.log(Direction.RIGHT); // 输出:"RIGHT"

(2)字符串枚举和数字枚举可以混合使用,形成 异构枚举(但通常不推荐):
enum Direction {
LEFT, // 数字枚举,值为 0
RIGHT = "RIGHT" // 字符串枚举
}
console.log(Direction.LEFT); // 输出:0
console.log(Direction.RIGHT); // 输出:"RIGHT"

4,常量枚举(const enum)
(1)在枚举定义前添加 const 关键字,可以定义 常量枚举。常量枚举在编译时会被内联,不会生成额外的运行时代码:
// 普通枚举
enum NormalEnum {
A,
B
}
// 常量枚举
const enum ConstEnum {
A,
B
}
// 使用枚举
let normal = NormalEnum.A; // 编译后:var normal = NormalEnum.A;
let constVal = ConstEnum.A; // 编译后:var constVal = 0;(直接内联)
(2)常量枚举与普通枚举的区别如下:
- 编译结果:常量枚举在编译阶段会被删除,枚举值直接内联到使用处;普通枚举会编译成实际的 JavaScript 对象。
- 反向映射:常量枚举没有反向映射功能;普通数字枚举支持反向映射。
- 性能:常量枚举访问时不需要属性查找,性能更好。
提示:在高性能场景下,推荐使用 const enum。但如果需要在运行时动态访问枚举值或使用反向映射,则必须使用普通枚举。
// 常量枚举示例
const enum Direction {
UP,
DOWN,
LEFT,
RIGHT
}
// 使用常量枚举
let directions = [Direction.UP, Direction.DOWN, Direction.LEFT, Direction.RIGHT];
// 编译后的 JavaScript 代码:
// var directions = [0 /* UP */, 1 /* DOWN */, 2 /* LEFT */, 3 /* RIGHT */];5,枚举的最佳实践
(1)在使用枚举时,建议遵循以下最佳实践:
- 状态管理:优先使用数字枚举,如订单状态、用户等级等。
- 配置选项:采用字符串枚举,保证语义清晰,便于调试。
- 性能优化:高频访问场景使用 const enum 减少运行时开销。
- 避免混用:慎用异构枚举(数字和字符串混用),保持代码一致性。
(2)下面是一个综合示例,展示枚举在实际项目中的应用:
提示:掌握字面量类型和枚举类型,能让我们的代码更加精确和安全。字面量类型适合简单的值约束,枚举类型适合复杂的业务场景。根据实际需求选择合适的类型,是 TypeScript 开发的重要技能。
// 订单状态枚举(数字枚举,便于状态机判断)
enum OrderStatus {
Pending = 0,
Paid = 1,
Shipped = 2,
Completed = 3,
Cancelled = 4
}
// 支付方式枚举(字符串枚举,语义清晰)
enum PaymentMethod {
CreditCard = "CREDIT_CARD",
WeChat = "WECHAT",
Alipay = "ALIPAY"
}
// 日志级别(常量枚举,高性能)
const enum LogLevel {
DEBUG = 0,
INFO = 1,
WARN = 2,
ERROR = 3
}
// 使用示例
function processOrder(status: OrderStatus) {
if (status === OrderStatus.Pending) {
console.log("订单待支付");
} else if (status >= OrderStatus.Paid) {
console.log("订单已处理");
}
}
processOrder(OrderStatus.Pending);
全部评论(0)