模块课程(2/2)
联合和缩小范围
在现实世界中,变量和 API 响应并不总是具有单一的固定类型。 TypeScript 提供联合类型来处理可变性,并提供类型缩小来在运行时安全地对其进行操作。
联合类型
联合类型允许变量接受不同类型的值。它使用竖线 (|) 符号表示:
let result: number | string;
result = 42; // Valid
result = 'Error 404'; // Valid但是,在使用联合类型时,我们不能直接调用仅属于其中一种类型的方法(例如,如果变量也可以是 number,则我们不能调用 .toUpperCase())。我们首先要“缩小”类型。
类型缩小
类型缩小是 TypeScript 分析控制流结构(例如 if 或 switch)以在运行时推断变量的更具体类型的过程。
有几种方法可以执行缩小:
1. typeof 运算符
区分原始类型的理想选择:
function printLength(value: string | number) {
if (typeof value === 'string') {
// TypeScript knows 'value' is a string here
console.log(value.length);
} else {
// TypeScript knows 'value' is a number here
console.log(value.toFixed(2));
}
}2. in 运算符
用于检查对象上是否存在特定属性:
interface Fish {
swim: () => void;
}
interface Bird {
fly: () => void;
}
function move(animal: Fish | Bird) {
if ('swim' in animal) {
animal.swim(); // Narrowing to Fish
} else {
animal.fly(); // Narrowing to Bird
}
}受歧视的工会
可区分联合模式包括创建共享具有唯一文字值(称为discriminator)的公共属性的对象。 TypeScript 可以识别这个鉴别器并自动缩小条件块内的类型范围。
interface SuccessResponse {
status: 'success'; // Literal discriminator
data: string;
}
interface ErrorResponse {
status: 'error'; // Literal discriminator
errorMessage: string;
}
type ApiResponse = SuccessResponse | ErrorResponse;
function handleResponse(response: ApiResponse) {
if (response.status === 'success') {
console.log('Data received:', response.data);
} else {
console.error('An error occurred:', response.errorMessage);
}
}自己尝试一下
练习 1:联合类型
声明一个名为 id 的变量,它可以是数字或字符串。首先使用数字 101 对其进行初始化,然后分配字符串值“USER-101”。
显示提示
使用 |运算符在 let 变量声明中连接数字和字符串。
3 次尝试后可用的解决方案
练习 2:基本类型缩小
创建一个名为 formatInput 的函数,该函数接受字符串或数字类型的参数输入。如果输入是字符串,则返回转换为大写的输入。如果是数字,则返回输入乘以 2。明确指定类型。
显示提示
在 if 块内使用 typeof input === 'string' 来分支行为。
3 次尝试后可用的解决方案
练习 3:用“in”缩小范围
给定两个接口 Car(使用drive方法)和Boat(使用方法sail),编写一个名为moveVehicle的函数,它接受Car或Boat类型的参数vehicle。如果车辆具有drive属性,则执行drive()方法。否则,执行 sail() 方法。
显示提示
在车辆中使用“drive”形式的 in 运算符来缩小界面范围。
3 次尝试后可用的解决方案
练习 4:可区分联合形状
定义一个 Shape 类型,它是两种类型的并集:Circle 和 Square。 Circle 有一个设置为“circle”(文字值)的种类属性和一个半径(数字)。 Square 有一个设置为“square”(文字值)的 kind 属性和一个边(数字)。然后编写一个函数 getArea,它接受 Shape 类型的形状并将面积作为数字返回(对于圆 Math.PI * radius * radius,对于正方形 side * side)。
显示提示
在 getArea 中使用 shape.kind === 'circle' 来区分类型并计算正确的面积。
3 次尝试后可用的解决方案