
TypeScript 系统入门到项目实战-慕课网-----97it.-----top/------469/
TypeScript 作为 JavaScript 的超集,凭借其强大的类型系统,已经成为现代前端开发的标配语言。除了基础类型(如 string
、number
、boolean
)外,TypeScript 还提供了更复杂、更灵活的类型机制,帮助开发者编写出更具健壮性和可维护性的代码。
本文将深入探讨 TypeScript 中三种关键的高级类型概念:联合类型(Union Types) 、交叉类型(Intersection Types) 和 泛型编程(Generic Programming) ,并结合实际案例分析它们的使用场景和底层原理。
一、联合类型(Union Types)
1.1 概念与语法
联合类型表示一个值可以是多个类型中的一种。使用 |
符号来分隔不同的类型。
ini
Ts
深色版本
let value: string | number;
value = "hello"; // 合法
value = 42; // 合法
1.2 使用场景
- 函数参数的多种输入类型
- API 返回值不确定时
- 状态字段可能有多种类型
scss
Ts
深色版本
function printId(id: number | string) {
console.log("ID is: " + id);
}
printId(100); // OK
printId("abc"); // OK
1.3 类型收窄(Type Narrowing)
由于联合类型在运行时无法直接知道具体是哪个类型,因此需要通过"类型守卫"进行判断:
typescript
Ts
深色版本
function padLeft(value: string | number, padding: string | number) {
if (typeof value === "number" && typeof padding === "number") {
return value + padding;
} else if (typeof value === "string" && typeof padding === "string") {
return padding + value;
}
throw new Error("Invalid arguments");
}
TypeScript 支持多种方式做类型收窄:
typeof
instanceof
- 自定义类型谓词函数(如
function isString(x): x is string
)
二、交叉类型(Intersection Types)
2.1 概念与语法
交叉类型表示一个值必须同时满足多个类型的特征。使用 &
符号组合多个类型。
ini
Ts
深色版本
type Person = { name: string };
type Employee = { id: number };
type Staff = Person & Employee;
const staff: Staff = {
name: "Alice",
id: 101
};
2.2 使用场景
- 混入多个接口功能
- 组合不同模块的功能对象
- 增强已有类型的属性
例如,在 React 开发中,经常用交叉类型扩展组件 props:
ini
Ts
深色版本
type WithLoading = { isLoading: boolean };
type WithError = { error: string | null };
type AppProps = WithLoading & WithError & {
title: string;
};
2.3 注意事项
- 如果两个类型中有相同属性但类型不同,TS 会报错。
ini
Ts
深色版本
type A = { prop: string };
type B = { prop: number };
type C = A & B; // 报错:'prop' has conflicting types
- 在合并函数类型时,返回类型也是联合类型。
ini
Ts
深色版本
type FnA = () => string;
type FnB = () => number;
type FnC = FnA & FnB; // 返回类型为 string | number
三、泛型编程(Generic Programming)
3.1 概念与语法
泛型允许我们编写与类型无关的代码,从而实现复用性更强、类型安全的函数和类。
csharp
Ts
深色版本
function identity<T>(arg: T): T {
return arg;
}
let output1 = identity<string>("hello"); // 推断为 string
let output2 = identity<number>(42); // 推断为 number
TypeScript 能够根据传入的参数自动推导类型:
ini
Ts
深色版本
let output3 = identity(true); // 推断为 boolean
3.2 泛型约束(Generic Constraints)
默认情况下,泛型变量 T
可以是任意类型,但有时我们需要限制它的范围。
scss
Ts
深色版本
interface Lengthwise {
length: number;
}
function logLength<T extends Lengthwise>(arg: T): void {
console.log(arg.length);
}
logLength("hello"); // OK
logLength([1, 2, 3]); // OK
logLength({ length: 5 }); // OK
logLength(42); // ❌ 报错:number 上没有 length 属性
3.3 泛型类与泛型接口
泛型不仅适用于函数,也可以用于类和接口:
ini
Ts
深色版本
class GenericNumber<T> {
zeroValue: T;
add: (x: T, y: T) => T;
}
let myGenericNumber = new GenericNumber<number>();
myGenericNumber.zeroValue = 0;
myGenericNumber.add = function(x, y) { return x + y; };
四、综合实战:构建一个类型安全的请求封装器
我们将结合联合类型、交叉类型与泛型,构建一个通用的 HTTP 请求封装器。
4.1 定义响应类型
ini
Ts
深色版本
type SuccessResponse<T> = {
success: true;
data: T;
};
type ErrorResponse = {
success: false;
error: string;
};
type ApiResponse<T> = SuccessResponse<T> | ErrorResponse;
4.2 封装泛型请求函数
vbnet
Ts
深色版本
async function fetchApi<T>(url: string): Promise<ApiResponse<T>> {
try {
const response = await fetch(url);
if (!response.ok) {
return { success: false, error: 'Network error' };
}
const data = await response.json();
return { success: true, data };
} catch (error) {
return { success: false, error: error.message };
}
}
4.3 使用示例
typescript
Ts
深色版本
interface User {
id: number;
name: string;
}
fetchApi<User>("/api/user")
.then(res => {
if (res.success) {
console.log(res.data.name); // 安全访问
} else {
console.error(res.error);
}
});
五、总结
TypeScript 的类型系统远不止于基础类型检查,它通过联合类型 、交叉类型 和泛型编程等机制,赋予了开发者极大的灵活性与类型安全性。
类型机制 | 特点 | 应用场景 |
---|---|---|
联合类型 (` | `) | 表示"或"的关系 |
交叉类型 (& ) |
表示"与"的关系 | 组合多个接口或类型 |
泛型 (<T> ) |
实现类型抽象 | 构建可复用、类型安全的函数/类 |
掌握这些高级类型技巧,不仅能提升代码质量,还能帮助你写出更具表达力和扩展性的程序结构。对于希望深入 TypeScript 编程的开发者来说,这是一条必经之路。