TypeScript 高级语法——泛型

基于前一篇对函数的基础认知我们可以更进一步了。
在官方文档上有这样一个例子,例子中我们在函数名后使用“<Type>”标记该函数为泛型函数,在实际使用中会根据实际使用的场景确定泛型占位标记Type的真实值。比如在使用firstElement1时Type为参数arr的类型,所以因为[ 1,2,3 ]的类型为Array<number>,则泛型占位Type的实际值为number[ ]。我们也可以显式的指定泛型占位标志的类型,如上例中被注掉的部分,多数时候我们都不需要显式声明,因为基于类型推断就已经能达到很好的效果。
在firstElement2函数中出现了“extends”关键字其意义表示为:类型Type是可以适配any数组的类型,官方称之为泛型约束,因为number数组是any数组的子集,所以将下方的firstElement1替换成firstElement2也一样可以正常运行。
上述泛型约束的例子只是为说明其逻辑的最简单示例,现实场景中需要开发人员为泛型提供有效约束,而不是any这种泛泛的约束(和没约束没什么区别),有效约束是比如泛型类型中必须有名为name 的字段之类,以下为正确示例:
在声明泛型函数时往往应该遵循最小泛型数量的设计:
在上例中filter1的可读性是完全高于filter2的,更少的泛型声明带给开发者的是更好的可读性与更少的神志负担,我们可以从函数体的类型依赖中推断出函数需要几个泛型占位标记(每种未在开发时确定的依赖类型算一个)。
interface也可以增加泛型标记,如上所示和泛型函数不同的是泛型接口必须显式的指定类型,上例的AppleBox是一个为确定实现的泛型接口起别名的操作,其中的泛型实现Apple是另一个接口。
介绍泛型的同时介绍一个只读数组类型ReadonlyArray,ReadonlyArray是TS定义的一个只读泛型数组类型,本质是一个泛型接口,其与Array类型最大的差异是ReadonlyArray不可被修改(无法使用具有副作用的函数,例如:push)。
泛型类和泛型接口完全相同,唯一的区别是类是ES标准中的概念,打包后依然以JS代码的形式存在,只不过属于类型描述的部分(泛型、参数类型声明)都消失了;而接口是TS的概念,无法转换为JS代码,所以泛型接口不会出现在打包后的代码中。