字面量类型
概述
字面量类型(Literal Types)是 TypeScript 中一种特殊的类型,它允许我们将具体的值作为类型使用。字面量类型包括字符串字面量、数字字面量和布尔字面量。通过字面量类型,我们可以创建更加精确和严格的类型约束,确保变量只能取特定的值,这在定义常量、配置选项和状态管理时非常有用。
基本语法
字面量类型直接使用具体的值作为类型:
typescript
// 字符串字面量类型
let direction: "up" = "up";
let status: "success" | "error" = "success";
// 数字字面量类型
let count: 42 = 42;
let port: 3000 | 8080 = 3000;
// 布尔字面量类型
let isTrue: true = true;
let isFalse: false = false;字符串字面量类型
字符串字面量类型允许我们指定变量只能是某个特定的字符串值:
typescript
// 单个字符串字面量类型
let event: "click" = "click";
// let event: "click" = "hover"; // ❌ 错误:只能赋值 "click"
// 多个字符串字面量类型(联合类型)
type Direction = "up" | "down" | "left" | "right";
let move: Direction = "up";
// let move: Direction = "diagonal"; // ❌ 错误:不在允许的值中
// 在函数中使用
function setDirection(direction: "up" | "down" | "left" | "right"): void {
console.log(`Moving ${direction}`);
}
setDirection("up"); // ✅ 正确
setDirection("down"); // ✅ 正确
// setDirection("north"); // ❌ 错误实际应用:配置选项
typescript
// 定义主题类型
type Theme = "light" | "dark" | "auto";
function setTheme(theme: Theme): void {
console.log(`Setting theme to: ${theme}`);
}
// 使用示例
setTheme("light"); // ✅ 正确
setTheme("dark"); // ✅ 正确
setTheme("auto"); // ✅ 正确
// setTheme("blue"); // ❌ 错误:类型不匹配
// 定义 HTTP 方法类型
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
function makeRequest(method: HttpMethod, url: string): void {
console.log(`Making ${method} request to ${url}`);
}
makeRequest("GET", "/api/users"); // ✅ 正确
makeRequest("POST", "/api/users"); // ✅ 正确
// makeRequest("OPTIONS", "/api/users"); // ❌ 错误数字字面量类型
数字字面量类型允许我们指定变量只能是某个特定的数字值:
typescript
// 单个数字字面量类型
let answer: 42 = 42;
// let answer: 42 = 43; // ❌ 错误:只能赋值 42
// 多个数字字面量类型(联合类型)
type DiceRoll = 1 | 2 | 3 | 4 | 5 | 6;
let roll: DiceRoll = 3;
// let roll: DiceRoll = 7; // ❌ 错误:不在允许的值中
// 定义端口号类型
type Port = 3000 | 8080 | 9000;
let serverPort: Port = 3000;实际应用:状态码和配置
typescript
// HTTP 状态码类型
type HttpStatus = 200 | 201 | 400 | 401 | 404 | 500;
function handleResponse(status: HttpStatus): void {
switch (status) {
case 200:
console.log("Success");
break;
case 404:
console.log("Not Found");
break;
case 500:
console.log("Server Error");
break;
}
}
handleResponse(200); // ✅ 正确
handleResponse(404); // ✅ 正确
// handleResponse(301); // ❌ 错误:不在允许的值中
// 定义 API 版本类型
type ApiVersion = 1 | 2 | 3;
function getApiUrl(version: ApiVersion): string {
return `https://api.example.com/v${version}`;
}
getApiUrl(1); // ✅ 正确
getApiUrl(2); // ✅ 正确
// getApiUrl(4); // ❌ 错误布尔字面量类型
布尔字面量类型允许我们指定变量只能是 true 或 false:
typescript
// 布尔字面量类型
let isActive: true = true;
let isDisabled: false = false;
// 在函数中使用
function setFeature(enabled: true): void {
console.log("Feature enabled");
}
setFeature(true); // ✅ 正确
// setFeature(false); // ❌ 错误:只能接受 true信息
虽然布尔字面量类型在技术上可行,但在实际开发中,使用 boolean 类型(true | false)更为常见和实用。布尔字面量类型主要用于某些特殊场景,如类型级编程。
字面量类型与类型推断
TypeScript 可以自动推断字面量类型,特别是当使用 const 声明时:
typescript
// const 声明的变量会被推断为字面量类型
const direction = "up"; // 类型推断为 "up"(字面量类型)
const count = 42; // 类型推断为 42(字面量类型)
const isActive = true; // 类型推断为 true(字面量类型)
// let 声明的变量会被推断为更宽泛的类型
let direction2 = "up"; // 类型推断为 string
let count2 = 42; // 类型推断为 number
let isActive2 = true; // 类型推断为 boolean
// 使用 as const 断言,强制推断为字面量类型
let direction3 = "up" as const; // 类型推断为 "up"
let count3 = 42 as const; // 类型推断为 42as const 断言
as const 断言可以将值标记为字面量类型,这在处理对象和数组时特别有用:
typescript
// 对象字面量
const config = {
theme: "dark",
port: 3000,
enabled: true
} as const;
// 此时 config.theme 的类型是 "dark"(字面量类型)
// config.port 的类型是 3000(字面量类型)
// config.enabled 的类型是 true(字面量类型)
// 数组字面量
const colors = ["red", "green", "blue"] as const;
// colors 的类型是 readonly ["red", "green", "blue"]
// colors[0] 的类型是 "red"(字面量类型)
// 使用示例
type Color = typeof colors[number]; // "red" | "green" | "blue"
let selectedColor: Color = "red"; // ✅ 正确
// let selectedColor: Color = "yellow"; // ❌ 错误使用示例
示例 1:状态管理
typescript
// 定义应用状态类型
type AppState = "idle" | "loading" | "success" | "error";
class StateManager {
private state: AppState = "idle";
setState(newState: AppState): void {
this.state = newState;
}
getState(): AppState {
return this.state;
}
}
// 使用示例
const manager = new StateManager();
manager.setState("loading"); // ✅ 正确
manager.setState("success"); // ✅ 正确
// manager.setState("pending"); // ❌ 错误:不在允许的状态中
// 状态处理函数
function handleState(state: AppState): void {
switch (state) {
case "idle":
console.log("应用空闲");
break;
case "loading":
console.log("加载中...");
break;
case "success":
console.log("操作成功");
break;
case "error":
console.log("操作失败");
break;
// TypeScript 会确保所有情况都被处理
}
}示例 2:API 响应类型
typescript
// 定义 API 响应类型
type ApiResponse<T> =
| { status: "success"; data: T }
| { status: "error"; message: string; code: number };
// 使用示例
function handleApiResponse<T>(response: ApiResponse<T>): void {
if (response.status === "success") {
// TypeScript 知道这里 response 有 data 属性
console.log("Data:", response.data);
} else {
// TypeScript 知道这里 response 有 message 和 code 属性
console.log("Error:", response.message, response.code);
}
}
// 创建响应对象
const successResponse: ApiResponse<string> = {
status: "success",
data: "Hello, World!"
};
const errorResponse: ApiResponse<string> = {
status: "error",
message: "Not found",
code: 404
};
handleApiResponse(successResponse); // ✅ 正确
handleApiResponse(errorResponse); // ✅ 正确示例 3:配置对象
typescript
// 定义配置类型
type LogLevel = "debug" | "info" | "warn" | "error";
type Environment = "development" | "staging" | "production";
type AppConfig = {
env: Environment;
logLevel: LogLevel;
port: 3000 | 8080 | 9000;
features: {
analytics: boolean;
caching: boolean;
};
};
// 创建配置函数
function createConfig(env: Environment): AppConfig {
const baseConfig: AppConfig = {
env,
logLevel: env === "production" ? "error" : "debug",
port: env === "production" ? 8080 : 3000,
features: {
analytics: env === "production",
caching: true
}
};
return baseConfig;
}
// 使用示例
const devConfig = createConfig("development");
const prodConfig = createConfig("production");
console.log(devConfig.logLevel); // "debug"
console.log(prodConfig.logLevel); // "error"字面量类型与联合类型
字面量类型经常与联合类型结合使用,创建精确的类型约束:
typescript
// 字符串字面量联合类型
type Status = "pending" | "completed" | "cancelled";
// 数字字面量联合类型
type Size = 8 | 16 | 32 | 64;
// 混合字面量类型
type Result = "success" | "error" | 0 | 1;
// 在函数中使用
function processResult(result: Result): void {
if (result === "success" || result === 1) {
console.log("Operation succeeded");
} else {
console.log("Operation failed");
}
}类型检查示例
常见错误
typescript
// ❌ 错误:赋值不在字面量类型中的值
type Direction = "up" | "down" | "left" | "right";
let dir: Direction = "diagonal"; // Error: Type '"diagonal"' is not assignable to type 'Direction'
// ❌ 错误:数字字面量类型不匹配
type Port = 3000 | 8080;
let port: Port = 9000; // Error: Type '9000' is not assignable to type 'Port'
// ❌ 错误:布尔字面量类型不匹配
let flag: true = false; // Error: Type 'false' is not assignable to type 'true'正确写法
typescript
// ✅ 正确:使用字面量类型
type Direction = "up" | "down" | "left" | "right";
let dir: Direction = "up";
// ✅ 正确:使用 const 声明自动推断为字面量类型
const direction = "up"; // 类型为 "up"
// ✅ 正确:使用 as const 断言
let direction2 = "up" as const; // 类型为 "up"
// ✅ 正确:在函数参数中使用
function move(direction: "up" | "down" | "left" | "right"): void {
console.log(`Moving ${direction}`);
}
move("up"); // ✅ 正确注意事项
提示
- 使用
const声明常量时,TypeScript 会自动推断为字面量类型,无需显式声明 - 使用
as const断言可以将对象和数组的属性推断为字面量类型 - 字面量类型与联合类型结合使用,可以创建非常精确的类型约束
注意
- 字面量类型是精确匹配,值必须完全相等(包括大小写、空格等)
- 字符串字面量类型区分大小写:
"Success"和"success"是不同的类型 - 数字字面量类型也区分具体的数值:
42和43是不同的类型
重要
字面量类型提供了编译时的类型安全,但不会影响运行时的行为。如果需要在运行时验证值是否在允许的范围内,需要额外的运行时检查。
相关链接
- 基础类型 - 了解 TypeScript 的基础类型系统
- 联合类型 - 学习如何组合字面量类型创建联合类型
- 类型别名 - 了解如何使用类型别名定义字面量类型
- 类型推断 - 了解 TypeScript 的类型推断机制
- TypeScript 官方文档 - 字面量类型