泛型的定义:
1.泛型(Generics)是指在定义函数、接口或类的时候,不预先指定具体的类型,而在使用的时候再指定类型的一种特性。
2.就是一种不确定的数据类型,可以把运行时的问题提前到编译时期(java里是这么说的 我觉得在ts 应该同理的)
3.简单粗暴的说不想丢失’ts’ 的类型检查
语法
直接在名称后写上<泛型名称>
命名规范
其中 T 代表 Type,在定义泛型时通常用作第一个类型变量名称。但实际上 T 可以用任何有效名称代替。除了 T 之外,以下是常见泛型变量代表的意思:
- K(Key):表示对象中的键类型;
- V(Value):表示对象中的值类型;
- E(Element):表示元素类型。
类型使用泛型
定义一个类型别名 type test<T> = T; const str:test<string> = '123'
接口使用泛型
interface T { name: T; }
函数使用泛型
fucntion test<T>(val: T): void{ }
类使用泛型
另见,手动实现ts 中的map函数
特点
1. 泛型相当于是一个类型变量,在定义时,无法预先知道具体的类型,可以用该变量来代替,只有到调用时,才能确定它的类型。很多时候,TS会智能的根据传递的参数,推导出泛型的具体类型
// 定义一个接口 interface Callback<T> { (val1: T, val2: T): T } // 定义一个求和的函数,传递两个参数,参数类型未知。求和的方式也未知 // 举个例子,我可以传两个数字进来,求乘积,或者求和, 或者我传入两个字符串,做凭借操作等 function sum<T>(val1: T, val2: T, cb: Callback<T>): T { return cb(val1, val2) } // 求数字的和 sum<number>(1, 2, (v1, v2) => { return v1 + v2; }) // 求字符串的拼接 sum<string>('a', 'b', (v1, v2) => { return v1 + v2; })
2. 如果无法完成推导,并且又没有传递具体的类型,默认为空对象 或者 unknown
样列代码,是手写的ts的map传送门
3. 泛型可以设置默认值
- 直接使用默认值, 对应的语法很简单,即 <T=Default Type>
// 定义一个含有默认类型的泛型接口 interface A<T=string> { name: T; } const strA: A = { name: "cll" }; // 这里会自动推导类型 const numB: A<number> = { name: 101 };
注意:泛型参数的默认类型遵循以下规则:
- 有默认类型的类型参数被认为是可选的。
- 必选的类型参数不能在可选的类型参数后。
- 如果类型参数有约束,类型参数的默认类型必须满足这个约束。
- 当指定类型实参时,你只需要指定必选类型参数的类型实参。未指定的类型参数会被解析为它们的默认类型。
- 如果指定了默认类型,且类型推断无法选择一个候选类型,那么将使用默认类型作为推断结果。
- 一个被现有类或接口合并的类或者接口的声明可以为现有类型参数引入默认类型。
- 一个被现有类或接口合并的类或者接口的声明可以引入新的类型参数,只要它指定了默认类型。
- 通过继承的方式
// 定义一个含有默认类型的泛型接口 interface A { name: string; } // 打印含有name 属性的方法 function consoleLogName<T extends A>(obj: T) { console.log(obj.name) }
调用方法需要传入满足条件的类型,关于ts 的类型兼容性检查, 另见
4. 多泛型
语法
直接在名称后写上<泛型名称1, 泛型名称2>
//将两个数组进行混合 //[1,3,4] + ["a","b","c"] = [1, "a", 3, "b", 4, "c"] function mixinArray<T, K>(arr1: T[], arr2: K[]): (T | K)[] { let result: (T | K)[] = []; //... 实现函数的混合 return result; } const result = mixinArray([1, 3, 4], ["a", "b", "c"]);