型(Generics)允许定义 可复用、可适应不同类型 的代码,而不需要在编写时就确定具体的类型。
function identity(value: T): T {
return value;
}
identity(123); // 指定 T 为 number
identity("hello"); // 指定 T 为 string
```
* T是一个 类型变量,表示函数可以接收任何类型。
* identity(123) 表示把 T 指定为 number。
* 如果不指定,TS 会自动 类型推断:
```
identity(true); // T 被推断为 boolean
```
### 2️⃣ 泛型接口
```
interface ApiResponse {
code: number;
message: string;
data: T;
}
const res1: ApiResponse = {
code: 200,
message: 'success',
data: 'Hello World'
};
const res2: ApiResponse = {
code: 200,
message: 'success',
data: [1, 2, 3]
};
```
* ApiResponse 表示 data 的类型是 泛型,可以是任何类型
### 3️⃣ 泛型类
```
class Box {
content: T;
constructor(value: T) {
this.content = value;
}
}
const stringBox = new Box('Hello');
const numberBox = new Box(123);
```
> Box 可以装任何类型的值,通过 new Box 或 new Box 来指定。
### 4️⃣ 泛型约束(extends)
有时候你希望泛型 必须满足某些条件,这时可以加 约束。
```
interface HasLength {
length: number;
}
function getLength(value: T): number {
return value.length;
}
getLength('Hello'); // OK
getLength([1, 2, 3]); // OK
getLength(123); // ❌ Error: number 没有 length 属性
```
### 5️⃣ 泛型默认值
```
function getValue(value: T): T {
return value;
}
getValue('hello'); // 推断为 string
getValue(123); // T 推断为 number
```
* 如果不传 T,默认是 string。
# 综合示例
```
type Field = {
label: string;
value: T;
};
const nameField: Field = { label: '姓名', value: '张三' };
const ageField: Field = { label: '年龄', value: 18 };
```
## 泛型工具函数
```
function merge(obj1: T, obj2: U): T & U {
return { ...obj1, ...obj2 };
}
const combined = merge({ name: '张三' }, { age: 18 }); // { name: string, age: number }
```
## 泛型 in TSX 组件
```
// GenericList.tsx
type GenericListProps = {
items: T[];
renderItem: (item: T) => JSX.Element;
};
function GenericList({ items, renderItem }: GenericListProps) {
return {items.map(renderItem)};
}
```
* 使用:
*
```
{item}
}
/>
```
## 泛型和 React/TS 项目常见用法
| 场景 | 示例 |
| -------- | --------------------- |
| API 响应类型 | `ApiResponse` |
| 通用工具函数 | `merge()` |
| 表单字段定义 | `Field` |
| 组件 props | `GenericComponent` |
| 状态管理 | `useState()` |
| 事件处理 | `onChange()` |
## 总结一张图理解
```
function func(param: T): T { ... }
↑
类型占位符,等调用时再指定具体类型
```
* T 可以是任何名字(常用 T、U、K、V)
* T 的值可以通过 调用时指定 或 TS 自动推断