TypeScript精华难点详解:理解与应用泛型
什么是泛型
整个ts的学习,其实就是各种数据类型的类型约束的学习。当我们规定一个变量只能是number
时,它就不能是其他数据类型。
let a: number = 20;
a = 'string' // 类型错误
在函数中也是一样,传入的参数类型,与返回的参数类型,都会被不同的约束规则约束。
function foo(a: number, b: string): string {
// todo
}
当然我们也知道,还可以使用interface,type
定义更为复杂的类型约束。可是这个时候我们就会面临一个问题。
以我们用的非常多的数组方法map
为例。
[1, 2, 3].map(item => {
return item + 1;
})
我们都知道map方法接收的第一个参数为一个回调函数callback
,callback
的第一个参数为数组的每一项。那么问题就来了,不同的数组调用map,数组的每一项数据类型必然不一样,我们没办法简单的使用某一种数据类型来准确的约束数组的每一项。
[1, 2, 3].map()
['a', 'b', 'c'].map()
怎么办?当数组不一样时?如何来约束呢?
这种情况,需要借助「泛型」来帮助我们。
单一的,明确的类型约束理解起来相对简单,可是实践中我们需要对约束稍微放宽一点限制,那么单一的约束就无法满足需求。泛型,即为更广泛的约束类型。
仔细观察下面的三组案例,思考一下如果我们要自己描述Array类型与数组中的map方法应该怎么做?
interface Person {
name: string,
age: number
}
const demo1: number[] = [1, 2, 3];
const demo2: string[] = ['a', 'b', 'c'];
const demo3: Person[] = [{ name: 'alex', age: 20 }, { name: 'john', age: 10 }, { name: 'hx', age: 21 }];
demo1.map((item) => item);
demo2.map((item) => item);
demo3.map((item) => item);
从图中可以看出,当不同的数组调用map时,回调函数的参数item,会自动推导为对应的数据类型。也就是说,这里的item,必然是使用了泛型进行了更为宽松的约束。具体如下:
interface Array<T> {
map<U>(callbackfn: (value: T, index: number, array: T[]) => U): U[]
}
我们在声明数组类型时,定义了一个泛型变量T
。T
作为泛型变量的含义为:我们在定义约束条件时,暂时还不知道数组的每一项数据类型到底是什么,因此我们只能放一个占位标识在这里,待具体使用时再来明确每一项的具体类型。
因此针对数据的描述,我们通常可以这样做:
const arr1: Array<number> = [1, 2, 3];
const arr2: Array<string> = ['a', 'b', 'c'];
const arr3: Array<Person> = [{ name: 'alex', age: 20 }, { name: 'john', age: 10 }, { name: 'hx', age: 21 }];
这里分别定义了三个数组,在约束这些数组时,我们明确了泛型变量T
的具体数据类型,分别对应为number, string, Person
。
那么在描述map时的写法就很好理解了。回调函数callbackfn
的第一个参数就是数组的每一项,正好就是定义数组时传入的泛型变量T
,不过回调函数会返回一个新的数组项,因此我们需要重新定义一个新的泛型变量来表达这个新数组,即为U
。
map<U>(callbackfn: (value: T, index: number, array: T[]) => U): U[]
于是我们就使用泛型,准确的描述了map方法的含义。
如果经过上述的解释还不清楚泛型概念的话,留言
推荐阅读
-
轻松理解 TypeScript 中的泛型 T 与 any 类型的不同之处
-
玩转现代TypeScript的高阶指南:深入理解泛型与类型操作艺术
-
轻松掌握 TypeScript 泛型及其实战应用详解 (7800字全攻略)
-
TypeScript实战笔记:详解类与泛型的运用实例,学习如何在TypeScript中玩转泛型,及其在提升代码灵活性与安全性的角色 - 青训营教程
-
TypeScript 初级教程 - 07章:理解与运用泛型
-
玩转 TypeScript:深入理解与实际运用中的泛型机制
-
深入理解 TypeScript:二代教程 - 泛型基础应用详解
-
理解 TypeScript 的泛型及其应用实例
-
玩转 TypeScript:理解与应用泛型
-
在 TypeScript 中,理解任意类型(type any)与泛型的差异之处