C33. 类型运算
3.1. 使用 & 和 | 运算符创建新类型
类型运算符允许组合现有类型,构建更复杂的类型。
3.1.1. 联合类型(Union Types) |
语法:
Type1 | Type2表示值可以是其中一种类型,需通过类型守卫确定具体类型。
typescript
// 示例:联合类型
let value: string | number;
value = "TypeScript"; // 合法
value = 42; // 合法
value = true; // ❌ 报错!类型不匹配
function logId(id: string | number) {
if (typeof id === "string") {
console.log(`ID是字符串: ${id}`);
} else {
console.log(`ID是数字: ${id}`);
}
}WARNING
联合类型需用 typeof、instanceof 或类型守卫缩小类型范围,否则无法调用特定方法(如 toUpperCase())。
3.1.2. 交叉类型(Intersection Types) &
语法:
Type1 & Type2合并多个类型的属性,形成新类型。
typescript
interface Dog {
bark(): void;
}
interface Bird {
fly(): void;
}
type SuperPet = Dog & Bird;
const pet: SuperPet = {
bark() { console.log("汪!") },
fly() { console.log("飞走了!") }
};3.2. 使用 ? 创建可选类型
在接口或类型中,用
?标记属性为可选。
typescript
interface User {
name: string;
age?: number; // 可选属性
}
const user1: User = { name: "Alice" }; // 合法
const user2: User = { name: "Bob", age: 30 }; // 合法
const user3: User = { }; // ❌ 必须提供 nameTIP
访问可选属性时建议使用可选链操作符(?.):
typescript
console.log(user.age?.toString()); // 若 age 不存在,返回 undefined3.3. 泛型(Generics)
泛型允许函数、接口或类操作“任意类型”,避免重复代码。
示例:泛型函数
typescript
// 泛型函数:返回传入的值
function identity<T>(arg: T): T {
return arg;
}
const num = identity<number>(42); // 显式指定类型参数
const str = identity("Hello"); // 类型推断自动推导为 string泛型接口
typescript
interface GenericIdentity {
<T>(arg: T): T;
}
const myIdentity: GenericIdentity = identity;INFO
泛型参数名通常用单字母:T(Type)、K(Key)、U(Type Union)等。
3.4. 使用 extends 对泛型约束
通过
extends限制泛型参数的类型,确保其具备特定属性。
typescript
// 约束为有 length 属性的类型
function logLength<T extends { length: number }>(arg: T): number {
return arg.length;
}
logLength("TypeScript"); // 合法,返回 10
logLength([1, 2, 3]); // 合法,返回 3
logLength(42); // ❌ 报错!number 没有 length 属性示例:约束为接口
typescript
interface HasId {
id: number;
}
function processItem<T extends HasId>(item: T): T {
item.id = 123;
return item;
}
const user = processItem({ id: 1, name: "Alice" }); // 合法
const invalid = processItem({ name: "Bob" }); // ❌ 缺少 id 属性3.5. 基础类型体操
通过组合类型运算符和泛型,实现灵活的类型操作。
示例:提取对象的键类型
typescript
type Keys = keyof { name: string; age: number }; // "name" | "age"示例:映射类型(基础)
typescript
type PartialUser<T> = {
[P in "name" | "age"]?: T; // 将指定属性改为可选
};
type User = PartialUser<string>; // { name?: string; age?: string }WARNING
类型操作需遵循 TypeScript 的类型推断规则,避免因类型过于复杂导致编译错误。
知识回顾
核心要点
- 类型运算符:
|:联合类型(值可为其中一种类型)。&:交叉类型(合并多个类型的属性)。?:定义可选属性。
- 泛型:
- 用
<T>定义类型参数,实现类型复用。 extends约束泛型参数的类型。
- 用
- 类型安全:
- 联合类型需用类型守卫缩小范围。
- 泛型约束确保参数具备必要属性。
- 类型体操:
- 使用
keyof提取属性名,通过映射类型自定义对象结构。
- 使用
课后练习
单选题:以下哪个运算符用于创建交叉类型?
- A.
| - B.
& - C.
+ - D.
*
- A.
填空题:定义一个泛型函数
identity,其类型应为<T>(arg: T) => T,代码为:function identity____(arg: T): T { return arg; }代码纠错:
typescriptinterface Animal { name: string; } function showName(animal: Animal | null) { return animal.name; // ❌ 报错!可能为 null }综合题:
- 定义一个接口
Rectangle,包含width和height属性。 - 使用交叉类型创建
Square,合并Rectangle和side: number属性。 - 编写一个泛型函数
getLength<T extends { length: number }>(arg: T),返回arg.length。 - 使用
extends约束泛型,确保传入对象包含id属性。
- 定义一个接口