认识泛型
软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能
在像C#和Java这样的语言中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。 这样用户就可以以自己的数据类型来使用组件
需要方法使返回值的类型与传入参数的类型是相同,使用 类型变量,特殊的变量,只表示类型而不是值
function foo<Type>(arg: <Type>): Type{ |
给foo
添加类型变量Type ,帮助我们捕获用户传入的类型(比如:number),我们再次使用 Tyep 当做返回值类型,知道参数类型与返回值类型是相同的
平时开发时没必要手动使用<类型>
传,因为类型推论可以自动完成
如果编译器不能够自动地推断出类型的,才手动传入
默认值,像函数参数一样也可以赋上默认值
function foo<Type = string>(arg: Type): Type{ |
平常使用类型变量名的缩写:
- T : Type的缩写
- K : key的缩写
- V : value的缩写
- E : Element的缩写
- O : Object的缩写
泛型接口
在定义接口的时候我们也可以使用泛型
interface IFoo<T = number> { |
泛型类
泛型类与泛型接口差不多。 泛型类使用<>
括起泛型类型,跟在类名后面
class Point<T> { |
泛型约束(Generic Constraints)
希望传入的类型有某些共性,但是这些共性可能不是在同一种类型中
- 比如string和array都是有length的,或者某些对象也是会有length属性的
- 那么拥有length的属性都可以作为参数类型
interface ILength { |
在泛型约束中使用类型参数
举个栗子:我们希望获取一个对象给定属性名的值
- 我们需要确保我们不会获取 obj 上不存在的属性
- 所以我们在两个类型之间建立一个约束
// 声明Type类型参数,Key 类型参数继承 Type里的key |
映射类型(Mapped Types)
一个类型需要基于另外一个类型,但你又不想拷贝一份,这个时候可以考虑使用映射类型。
- 大部分内置的工具都是通过映射类型来实现
- 大多数类型体操的题目也是通过映射类型完成
映射类型建立在索引签名上
- 映射类型,就是使用了 PropertyKeys 联合类型的泛型
- PropertyKeys 多是通过 keyof 创建,然后循环遍历
interface IPerson { |
映射修饰符(Mapping Modifiers)
在使用映射类型时,有两个额外的修饰符可能会用到:
readonly
: 用于设置属性只读;?
: 用于设置属性可选;
修饰符可添加前缀 - 或者 + 删除或者添加这些修饰符
如果没有写前缀,相当于使用了 + 前缀
类型体操练习网站
条件类型(Conditional Types)
条件类型(Conditional types)就是用来帮助我们描述输入类型和输出类型之间的关系
写法类似 三目运算符SomeType extends OtherType ? TrueType : FalseType
function foo<T extends number | string>(arg1: T, arg2: T):T extends string?string:number{ |