第8章:类型系统进阶
联合类型与交叉类型
1. 联合类型(Union Types)
联合类型允许一个值属于多种类型之一,通过 | 符号连接多个类型。
语法示例:
let value: string | number;
value = "Hello"; // 合法
value = 42; // 合法
value = true; // 错误:boolean 不在联合类型中
特点:
- 提供灵活性,适用于不确定具体类型的场景(如 API 返回的数据可能是字符串或数字)。
- 需配合类型保护(Type Guards)缩小类型范围,才能安全访问特定类型的属性或方法。
类型保护示例:
function printValue(value: string | number) {
if (typeof value === "string") {
console.log(value.toUpperCase()); // 安全调用字符串方法
} else {
console.log(value.toFixed(2)); // 安全调用数字方法
}
}
2. 交叉类型(Intersection Types)
交叉类型将多个类型合并为一个类型,通过 & 符号连接。新类型包含所有成员的属性和方法。
语法示例:
interface Person {
name: string;
}
interface Employee {
id: number;
}
type Staff = Person & Employee;
const staff: Staff = {
name: "Alice",
id: 123, // 必须同时满足 Person 和 Employee
};
特点:
- 常用于组合多个接口或类型别名(如混入模式 Mixins)。
- 若存在同名属性且类型冲突,会导致该属性变为
never类型(不可用)。
冲突示例:
type A = { foo: string };
type B = { foo: number };
type C = A & B;
// foo 的类型为 string & number → never
3. 联合类型 vs 交叉类型
| 特性 | 联合类型 | 交叉类型 |
|---|---|---|
| 符号 | ` | ` |
| 语义 | “或”关系 | “与”关系 |
| 使用场景 | 不确定具体类型时 | 合并多个类型的特性时 |
| 类型保护 | 必须使用 | 通常不需要 |
4. 实际应用场景
联合类型的典型用例:
- 处理异构数据:如 API 响应可能返回成功或错误两种结构。
type ApiResponse = SuccessResponse | ErrorResponse; - 组件 Props:React 组件支持多种类型的属性。
type ButtonProps = PrimaryProps | SecondaryProps;
交叉类型的典型用例:
- 扩展对象:合并多个工具函数的返回值。
function extend<T, U>(first: T, second: U): T & U { return { ...first, ...second }; } - 组合配置:合并默认配置与用户自定义配置。
type DefaultConfig = { timeout: number }; type UserConfig = { retry: boolean }; type FinalConfig = DefaultConfig & UserConfig;
5. 注意事项
- 类型推断:联合类型在赋值时会推断为最宽泛的可能类型,交叉类型会严格合并。
- 性能影响:复杂交叉类型可能增加编译时类型检查的负担,需适度使用。
