Skip to content

TypeScript 高级类型

在掌握了 TypeScript 的基础类型后,本章节将介绍 TypeScript 的高级类型,这些类型可以帮助你构建更复杂、更灵活的类型系统。

联合类型

联合类型表示一个值可以是几种类型中的一种,使用 | 符号分隔不同的类型。

示例:

typescript
// 联合类型:字符串或数字
let value: string | number;
value = "Hello";
value = 42;

// 联合类型:布尔或字符串数组
let result: boolean | string[];
result = true;
result = ["a", "b", "c"];

// 联合类型的使用
function printValue(value: string | number): void {
  if (typeof value === "string") {
    console.log(`String: ${value}`);
  } else {
    console.log(`Number: ${value}`);
  }
}

printValue("Hello"); // String: Hello
printValue(42); // Number: 42

交叉类型

交叉类型表示一个值同时具有多种类型的特性,使用 & 符号连接不同的类型。

示例:

typescript
// 定义两个接口
interface Person {
  name: string;
  age: number;
}

interface Employee {
  employeeId: number;
  department: string;
}

// 交叉类型:同时具有 Person 和 Employee 的特性
type Staff = Person & Employee;

// 使用交叉类型
const staff: Staff = {
  name: "John",
  age: 30,
  employeeId: 12345,
  department: "IT"
};

console.log(staff.name); // John
console.log(staff.employeeId); // 12345

类型别名

类型别名允许你为一个类型定义一个新的名称,使用 type 关键字。

示例:

typescript
// 为基本类型创建别名
type StringOrNumber = string | number;

// 使用类型别名
let value: StringOrNumber;
value = "Hello";
value = 42;

// 为对象类型创建别名
type User = {
  id: number;
  name: string;
  email: string;
};

// 使用类型别名
const user: User = {
  id: 1,
  name: "John",
  email: "john@example.com"
};

// 为函数类型创建别名
type AddFunction = (a: number, b: number) => number;

// 使用类型别名
const add: AddFunction = (a, b) => a + b;
console.log(add(1, 2)); // 3

字面量类型

字面量类型表示一个具体的值,而不是一个类型范围。

示例:

typescript
// 字符串字面量类型
type Direction = "up" | "down" | "left" | "right";

let direction: Direction;
direction = "up"; // 正确
direction = "down"; // 正确
// direction = "north"; // 错误:Type '"north"' is not assignable to type 'Direction'

// 数字字面量类型
type DiceRoll = 1 | 2 | 3 | 4 | 5 | 6;

let roll: DiceRoll;
roll = 3; // 正确
// roll = 7; // 错误:Type '7' is not assignable to type 'DiceRoll'

// 布尔字面量类型
type BooleanLiteral = true | false;

let isActive: BooleanLiteral;
isActive = true; // 正确
// isActive = "true"; // 错误:Type '"true"' is not assignable to type 'BooleanLiteral'

可选类型

可选类型表示一个属性或参数是可选的,使用 ? 符号标记。

示例:

typescript
// 可选属性
interface User {
  id: number;
  name: string;
  email?: string; // 可选属性
  age?: number; // 可选属性
}

// 创建用户对象,可以不提供可选属性
const user1: User = {
  id: 1,
  name: "John"
};

// 也可以提供可选属性
const user2: User = {
  id: 2,
  name: "Jane",
  email: "jane@example.com",
  age: 25
};

// 可选参数
function greet(name: string, greeting?: string): string {
  if (greeting) {
    return `${greeting}, ${name}!`;
  }
  return `Hello, ${name}!`;
}

greet("John"); // Hello, John!
greet("John", "Hi"); // Hi, John!

非空断言

非空断言用于告诉 TypeScript 编译器,一个值不是 nullundefined,使用 ! 符号。

示例:

typescript
// 非空断言
let element: HTMLElement | null = document.getElementById("myElement");
// 告诉编译器 element 不是 null
let length: number = element!.textContent!.length;

// 非空断言在函数返回值中的使用
function getElement(id: string): HTMLElement | null {
  return document.getElementById(id);
}

// 告诉编译器返回值不是 null
let myElement: HTMLElement = getElement("myElement")!;

注意: 非空断言是一个编译时特性,它不会在运行时进行检查。如果实际值是 nullundefined,运行时仍然会报错。因此,使用非空断言时要确保值确实不是 nullundefined

unknown 类型

unknown 类型是 TypeScript 3.0 引入的一种安全的 any 类型,它表示一个未知类型的值。与 any 不同,unknown 类型的值不能直接使用,需要进行类型检查或类型断言。

示例:

typescript
// unknown 类型
let unknownValue: unknown;
unknownValue = 42;
unknownValue = "Hello";
unknownValue = true;

// unknown 类型的值不能直接使用
// let length: number = unknownValue.length; // 错误:Object is of type 'unknown'

// 需要进行类型检查
if (typeof unknownValue === "string") {
  let length: number = unknownValue.length; // 正确
  console.log(length);
}

// 或者使用类型断言
let stringValue = unknownValue as string;
let length: number = stringValue.length; // 正确

类型守卫

类型守卫是一种运行时检查,用于确定一个值的类型,以便在类型安全的情况下使用它。

typeof 类型守卫

typescript
function processValue(value: string | number): void {
  if (typeof value === "string") {
    // 在这里,value 被推断为 string 类型
    console.log(`String length: ${value.length}`);
  } else {
    // 在这里,value 被推断为 number 类型
    console.log(`Number value: ${value.toFixed(2)}`);
  }
}

processValue("Hello"); // String length: 5
processValue(42); // Number value: 42.00

instanceof 类型守卫

typescript
class Animal {
  name: string;
  constructor(name: string) {
    this.name = name;
  }
}

class Dog extends Animal {
  bark(): void {
    console.log("Woof!");
  }
}

class Cat extends Animal {
  meow(): void {
    console.log("Meow!");
  }
}

function makeSound(animal: Animal): void {
  if (animal instanceof Dog) {
    // 在这里,animal 被推断为 Dog 类型
    animal.bark();
  } else if (animal instanceof Cat) {
    // 在这里,animal 被推断为 Cat 类型
    animal.meow();
  } else {
    console.log(`Animal ${animal.name} makes a sound`);
  }
}

const dog = new Dog("Rex");
const cat = new Cat("Whiskers");
const animal = new Animal("Generic");

makeSound(dog); // Woof!
makeSound(cat); // Meow!
makeSound(animal); // Animal Generic makes a sound

自定义类型守卫

typescript
interface User {
  id: number;
  name: string;
  email: string;
}

interface Admin {
  id: number;
  name: string;
  role: string;
}

// 自定义类型守卫
function isAdmin(user: User | Admin): user is Admin {
  return "role" in user;
}

function processUser(user: User | Admin): void {
  if (isAdmin(user)) {
    // 在这里,user 被推断为 Admin 类型
    console.log(`Admin ${user.name} has role ${user.role}`);
  } else {
    // 在这里,user 被推断为 User 类型
    console.log(`User ${user.name} has email ${user.email}`);
  }
}

const user: User = {
  id: 1,
  name: "John",
  email: "john@example.com"
};

const admin: Admin = {
  id: 2,
  name: "Jane",
  role: "admin"
};

processUser(user); // User John has email john@example.com
processUser(admin); // Admin Jane has role admin

实战:使用高级类型

示例 1:使用联合类型和类型守卫

typescript
// 定义联合类型
type PaymentMethod = "credit card" | "paypal" | "bank transfer";

// 定义支付信息接口
interface PaymentInfo {
  method: PaymentMethod;
  amount: number;
  // 不同支付方式的特定属性
  cardNumber?: string;
  paypalEmail?: string;
  bankAccount?: string;
}

// 处理支付
function processPayment(payment: PaymentInfo): void {
  console.log(`Processing payment of $${payment.amount} via ${payment.method}`);
  
  // 使用类型守卫检查支付方式
  switch (payment.method) {
    case "credit card":
      if (payment.cardNumber) {
        console.log(`Card number: ${payment.cardNumber}`);
      }
      break;
    case "paypal":
      if (payment.paypalEmail) {
        console.log(`PayPal email: ${payment.paypalEmail}`);
      }
      break;
    case "bank transfer":
      if (payment.bankAccount) {
        console.log(`Bank account: ${payment.bankAccount}`);
      }
      break;
  }
}

// 使用
const creditCardPayment: PaymentInfo = {
  method: "credit card",
  amount: 100,
  cardNumber: "1234-5678-9012-3456"
};

const paypalPayment: PaymentInfo = {
  method: "paypal",
  amount: 50,
  paypalEmail: "user@example.com"
};

processPayment(creditCardPayment);
processPayment(paypalPayment);

示例 2:使用交叉类型和类型别名

typescript
// 定义基础用户类型
type BaseUser = {
  id: number;
  name: string;
  email: string;
};

// 定义角色类型
type Role = "user" | "admin" | "moderator";

// 定义用户类型,使用交叉类型
 type UserWithRole = BaseUser & {
  role: Role;
  lastLogin: Date;
};

// 定义管理员类型,使用交叉类型
 type AdminUser = UserWithRole & {
  permissions: string[];
  department: string;
};

// 使用
const user: UserWithRole = {
  id: 1,
  name: "John",
  email: "john@example.com",
  role: "user",
  lastLogin: new Date()
};

const admin: AdminUser = {
  id: 2,
  name: "Jane",
  email: "jane@example.com",
  role: "admin",
  lastLogin: new Date(),
  permissions: ["manage users", "manage content"],
  department: "IT"
};

console.log(user.name); // John
console.log(admin.permissions); // ["manage users", "manage content"]

小结

本章节介绍了 TypeScript 的高级类型,包括:

  • 联合类型 string | number
  • 交叉类型 type A = B & C
  • 类型别名 type
  • 字面量类型
  • 可选类型 ?
  • 非空断言 !
  • unknown 类型(安全版 any)
  • 类型守卫(typeof、instanceof、自定义类型守卫)

这些高级类型可以帮助你构建更复杂、更灵活的类型系统,提高代码的类型安全性和可维护性。在实际开发中,应该根据具体需求选择合适的类型,以充分利用 TypeScript 的类型系统优势。

© 2026 编程马·菜鸟教程 版权所有