组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能
1、泛型
我们给identity3添加了类型变量T。T帮助我们捕获用户的传入的类型(比如:Number),之后我们就可以使用这个类型。之后我们再次使用了T当做返回值类型。现在我们可以知道参数类型与返回值类型是相同的了。
这允许我们跟踪函数里使用的类型的信息
我们把identity3函数叫做泛型,因为它可以适用于多个类型。不同于使用any,它不会丢失信息,像第一个例子那样保持准确性,传入数值类型并返回数值类型
我们定义了泛型函数后,可以用两种方法使用
对于output2我们没有使用尖括号<>来明确的传入类型;编译器可以查看 4 的值,然后把T设置为它的类型。类型推论帮助我们保持代码精简和高可读性。如果编译器不能够自动地推断出类型的话,只能像上面那样明确的传入T的类型。
2、使用泛型变量
我们也可以将泛型变量T 当做类型的一部分使用,而不是作为整个类型,如下:
3、泛型类型
上一节,我们创建了identity通用函数,可以适用于不同的类型。在这节,我们研究了一下函数本身的类型,以及如何创建泛型接口
我们也可以使用不同的泛型参数名,只要在数量上和使用方式上能对应上就可以
我们还可以使用带有调用签名的对象字面量来定义泛型函数
这就引导我们去写第一个泛型接口,把上面例子中的对象字面量拿出来作为一个接口
我们可以把泛型参数当做整个接口的一个参数。这样我们就能清楚的知道使用的具体是哪个泛型类型
注意:不能创建泛型枚举和泛型命名空间
4、泛型类
泛型类看上去和泛型接口差不多。泛型类使用<>括起泛型类型,跟在类名后面
与接口一样,直接把泛型类型放在类后面,可以帮助我们确认类的所有属性都在使用相同的类型。
我们在类章节说过,类有两部分:静态部分和实例部分。泛型类型指的是实例部分的类型,所以类的静态属性不能使用这个泛型类型
5、泛型约束
我们直接操作泛型类型的参数,但是编译器不能证明每种类型都有length属性,所以就会报错
相比于操作any所有类型,我们想要限制函数去处理带有.length属性的所有类型。只要传入的类型有这个属性。我们就允许,就是说至少包含这一个属性。为此,我们需要列出对于T的约束要求
为此,我们定义一个接口来描述约束条件。创建一个包含.lenght属性的接口,使用这个接口和extends关键字来实现约束
在泛型约束中使用类型参数
如果键值不属于对象,则会报错
在泛型里使用类类型
使用原型属性推断并约束构造函数与类实例的关系