为什么要用泛型
- 许多时候,标注的具体类型并不能确定,比如一个函数的参数类型
- 这个时候这种定义过程不确定类型的需求就可以通过泛型来解决
- 泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性
-
泛型函数
首先,我们来实现一个函数 createArray,它可以创建一个指定长度的数组,同时将每一项都填充一个默认值
function createArray(length: number, value: any): Array<any> {let result: any = []for (let i = 0; i < length; i++) {result[i] = value}return result}let result = createArray(3, 'x')
如果像这样将传入参数设置为any类型,不能得到准确的返回类型
如果使用泛型,我们就能约束我们想要的结果
function createArray2<T>(length: number, value: T): Array<T> {let result: T[] = []for (let i = 0; i < length; i++) {result[i] = value}return result}let result2 = createArray2<string>(3, 'x')
泛型类
class MyArray<T> {private list: T[] = []add(value: T) {this.list.push(value)}getMax(): T {let result = this.list[0]for (let i = 0; i < this.list.length; i++) {if (this.list[i] > result) {result = this.list[i]}}return result}}let arr = new MyArray<number>()arr.add(1)arr.add(2)arr.add(3)let ret = arr.getMax()console.log(ret)
泛型与new
function factory<T>(type: { new (): T }): T {return new type()}const arr = factory<string[]>(Array)
泛型接口
- 泛型接口可以用来约束函数
后端提供了一些接口,用以返回一些数据,依据返回的数据格式定义如下接口:
interface IResponseData {code: number;message?: string;data: any; // 现在无法确定接口数据类型}
- 但是,我们会发现该接口的 data 项的具体类型不确定,不同的接口会返回的数据是不一样的
- 当我们想根据具体当前请求的接口返回具体 data 格式的时候,就比较麻烦了,因为 getData 并不清楚你调用的具体接口是什么,对应的数据又会是什么样的
- 这个时候我们可以对 接口数据IResponseData 使用泛型
```typescript
interface IResponseData
{ code: number message?: string data: T }
// 用户接口 interface IResponseUserData { id: number username: string email: string } // 文章接口 interface IResponseArticleData { id: number title: string author: IResponseUserData }
async function getData(url: string) {
let response = await fetch(url)
let data: Promise
;(async function () {
let userData = await getData
let articleData = await getData
<a name="KSA0g"></a>## 多个泛型```typescriptfunction swap<A, B>(tuple: [A, B]): [B, A] {return [tuple[1], tuple[0]]}let swapped = swap<string, number>(['a', 1])console.log(swapped)console.log(swapped[0].toFixed(2))console.log(swapped[1].length)
泛型约束
- 在函数中使用泛型的时候,由于预先并不知道泛型的类型,所以不能随意访问相应类型的属性或方法。
```typescript
function logger
(val: T) { console.log(val.length) //直接访问会报错 } //可以让泛型继承一个接口 interface LengthWise { length: number } //可以让泛型继承一个接口 function logger2 (val: T) { console.log(val.length) } logger2(‘acg’) logger2(1)
```
