可以使用泛型来创建高可用的类、类型、接口和函数。
最经典的来自官方文档的例子:
1
2
3
|
function identity(argument: number): number {
return argument;
}
|
上面的函数返回我们传递给它的参数。 不幸的是,这意味着我们需要为每种返回类型创建一个函数,这并不符合可重用性的标准。为了改进代码,我们可以引入类型变量,要声明一个类型变量,我们需要使用 function identity<T>
来命名函数:
1
2
3
|
function identity<T>(argument: T): T {
return argument;
}
|
上面的代码表示 argument
和 identity
函数返回的类型应该是相同的。
我们可以显式传入类型参数,也可以使用类型推断:
1
2
3
|
identity<string>("Hello world!");
// 或是
identity("Hello world!");
|
箭头函数
也可以使用箭头函数重写一下:
1
|
const identity = <T>(argument: T): T => argument;
|
在 .tsx
文件中会报错 JSX 元素“T”没有相应的结束标记。
,要怎么解决这个问题呢,应该复写一下:
1
|
const identity = <T,>(argument: T): T => argument;
|
更常见的例子
基于 Promise 的Fetch API功能强大且灵活,在定义类型时,泛型就格外适用。
1
2
3
4
5
6
7
8
|
function request<T>(url: string, options?: RequestInit): Promise<T> {
return fetch(url, options).then((response) => {
if (!response.success) {
return Promise.reject();
}
return response.json();
});
}
|
上面的代码是个简略版,当返回数据没有 body 时json() 方法可能会报错,需要做更多的一些判断来让上面这段代码更加可靠。
怎么使用呢,如下:
1
2
3
4
5
6
7
8
9
10
11
12
|
interface User {
id: number;
name: string;
email: string;
}
request<User[]>('https://jsonplaceholder.typicode.com/users')
.then((users) => {
console.log(`There are ${users.length} users`);
}).catch(error) => {
console.error(error)
});
|
通过 request<User[]>('https://jsonplaceholder.typicode.com/users')
调用可以表明返回的数据是 User
数组。
泛型接口和类
除了用内置的例如 Promise
等接口,我们还可以创建我们自己的:
1
2
3
4
5
6
7
8
9
|
interface KeyValuePair<K, V> {
key: K;
value: V;
}
const keyValuePair: KeyValuePair<string, number> = {
key: "name",
value: 15,
};
|
我们也可以创建通用类:
1
2
3
4
5
6
7
8
9
|
class KeyValuePair <K, V> {
public key: K;
public value: V;
constructor(key: K, value: V) {
this.key = key;
this.value = value;
}
}
const keyValuePair = new KeyValuePair('name', 15);
|