Skip to content

字面量类型

概述

字面量类型(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);  // ❌ 错误

布尔字面量类型

布尔字面量类型允许我们指定变量只能是 truefalse

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;        // 类型推断为 42

as 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" 是不同的类型
  • 数字字面量类型也区分具体的数值:4243 是不同的类型

信息

字面量类型在以下场景特别有用:

  • 定义常量集合(如状态、配置选项)
  • 创建精确的 API 接口类型
  • 实现类型安全的枚举替代方案
  • 联合类型结合创建可辨识联合(Discriminated Unions)

重要

字面量类型提供了编译时的类型安全,但不会影响运行时的行为。如果需要在运行时验证值是否在允许的范围内,需要额外的运行时检查。

相关链接

基于 VitePress 构建