# 5. 泛型 指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定具体类型的一种特性。 ## 引入 下面创建一个函数, 实现功能: 根据指定的数量 `count` 和数据 `value` , 创建一个包含 `count` 个 `value` 的数组 不用泛型的话,这个函数可能是下面这样: ```typescript function createArray(value: any, count: number): any[] { const arr: any[] = [] for (let index = 0; index < count; index++) { arr.push(value) } return arr } const arr1 = createArray(11, 3) const arr2 = createArray('aa', 3) console.log(arr1[0].toFixed(), arr2[0].split('')) ``` ## 使用函数泛型 ```typescript function createArray2 (value: T, count: number) { const arr: Array = [] for (let index = 0; index < count; index++) { arr.push(value) } return arr } const arr3 = createArray2(11, 3) console.log(arr3[0].toFixed()) // console.log(arr3[0].split('')) // error const arr4 = createArray2('aa', 3) console.log(arr4[0].split('')) // console.log(arr4[0].toFixed()) // error ``` ## 多个泛型参数的函数 一个函数可以定义多个泛型参数 ```typescript function swap (a: K, b: V): [K, V] { return [a, b] } const result = swap('abc', 123) console.log(result[0].length, result[1].toFixed()) ``` ## 泛型接口 在定义接口时, 为接口中的属性或方法定义泛型类型 在使用接口时, 再指定具体的泛型类型 ```typescript interface IbaseCRUD { data: T[] add: (t: T) => void getById: (id: number) => T } class User { id?: number; //id主键自增 name: string; //姓名 age: number; //年龄 constructor (name, age) { this.name = name this.age = age } } class UserCRUD implements IbaseCRUD { data: User[] = [] add(user: User): void { user = {...user, id: Date.now()} this.data.push(user) console.log('保存user', user.id) } getById(id: number): User { return this.data.find(item => item.id===id) } } const userCRUD = new UserCRUD() userCRUD.add(new User('tom', 12)) userCRUD.add(new User('tom2', 13)) console.log(userCRUD.data) ``` ## 泛型类 在定义类时, 为类中的属性或方法定义泛型类型 在创建类的实例时, 再指定特定的泛型类型 ```typescript class GenericNumber { zeroValue: T add: (x: T, y: T) => T } let myGenericNumber = new GenericNumber() myGenericNumber.zeroValue = 0 myGenericNumber.add = function(x, y) { return x + y } let myGenericString = new GenericNumber() myGenericString.zeroValue = 'abc' myGenericString.add = function(x, y) { return x + y } console.log(myGenericString.add(myGenericString.zeroValue, 'test')) console.log(myGenericNumber.add(myGenericNumber.zeroValue, 12)) ``` ## 泛型约束 如果我们直接对一个泛型参数取 `length` 属性, 会报错, 因为这个泛型根本就不知道它有这个属性 ```typescript // 没有泛型约束 function fn (x: T): void { // console.log(x.length) // error } ``` 我们可以使用泛型约束来实现 ```typescript interface Lengthwise { length: number; } // 指定泛型约束 function fn2 (x: T): void { console.log(x.length) } ``` 我们需要传入符合约束类型的值,必须包含必须 `length` 属性: ```typescript fn2('abc') // fn2(123) // error number没有length属性 ```