大部分的编译型语言都有泛型
可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。这样用户就可以以自己的数据类型来使用组件。
泛型
在TS当中, 泛型可以用于方法也可以用于类
用于函数的泛型
1 | function test<T>(arg: T):T { |
这种情况下调用该函数时就可以明确知道该函数的返回值类型与传入的第一个参数是相同的
上面的代码当中第二次调用函数时并未指定泛型, 这种情况下就是利用TS类型推断的机制, 根据第一个参数的类型来进行推断
函数类型的表示方法
如果要为一个变量指定为函数类型, 由于函数包含多种要素, 有参数类型, 返回值类型, 还可能包含泛型
比如上面的test函数, 要用一个变量来接收这个函数的话就是
1 | let t1: {<T>(arg: T): T} = test |
泛型的参数名并不要求必须一致
用于类的泛型
1 | class Demo<T> { |
类的静态成员不能使用泛型
泛型约束
上面的方式写的泛型, 实际使用的时候相当于any, 也就是该泛型可以是任意类型
如果要约束这个泛型的类型范围
和Java当中一样, 也是使用extends
关键字 ( 并没有super )
1 | class Demo1{ |
注意 : 这里的
T extends Demo1
只是代表传入的泛型必须具备Demo1所有的成员
而不是必须是Demo1或者以extends Demo1来声明的类
比如有如下代码
1 | class Test { |
可以看到上述的几个类都没有继承自Test, 但是如果具备与Test相同的成员, 即可指定为Demo类的泛型
查找类型
查找类型是 TS2.1 引入的新语法, 与之相关的关键字就是keyof
和type
使用它获得的结果是一个union, 可以在泛型当中使用
(关于TS当中的union, 后面会提到)
1 | interface Demo { |
keyof 后面跟的是一个类型(可以是类或者接口)
返回的是这个类型当中所有成员的名称
使用type关键字可以获取一个类或者接口当中指定成员的类型
当然不只是适用于自定义的类
比如
1 | type b = string['charAt'] |
union
如果需要表示多种类型或值的组合, 可以使用union
它是一种类型, 可以用在任何需要使用类型的地方
这个类型中可以包含类型或者具体的对象
1 | type myType = string | 0 |
元组(Tuple)
第一次知道这种结构还是在python当中
当然原生JS没有元组了, TS实现了元组(Tuple)
, 目的是合并不同类型的对象
而数组合并的是相同类型的对象
1 | let t: [string, number, Date] = ['123', 10, new Date()] |
其实完全可以把它看做一个数组, 实际的用法也和数组一样
枚举
TS也具备枚举类型, 与其他语言一样, 枚举可以用于清晰地表达意图或创建一组有区别的元素
比起直接使用数字表示, 代码更加清晰易读
1 | // 不指定数字, 从0开始的连续序列 |
翻译后的JavaScript代码
1 | ; |
可以看到它依然是用JS的键值对结构对象模拟实现的, 但是更多的时候我们不需要管这些
只需要按照熟知的枚举特点去使用
比如它是有固定数量实例的一种类型, 可以用于switch语句等等