TypeScript泛型
TypeScript泛型
Jin认识泛型
软件工程中,我们不仅要创建一致的定义良好的API,同时也要考虑可重用性。 组件不仅能够支持当前的数据类型,同时也能支持未来的数据类型,这在创建大型系统时为你提供了十分灵活的功能
在像C#和Java这样的语言中,可以使用泛型来创建可重用的组件,一个组件可以支持多种类型的数据。 这样用户就可以以自己的数据类型来使用组件
需要方法使返回值的类型与传入参数的类型是相同,使用 类型变量,特殊的变量,只表示类型而不是值
function foo<Type>(arg: <Type>): Type{
return arg
}
// 参数类型为 number
const num = foo<number>(123)
// string
const str = foo<string>('hello')
// 类型推论,根据传入的参数自动确定Type的类型
const hello = foo('hello world') // type of output will be 'string'
给foo
添加类型变量Type ,帮助我们捕获用户传入的类型(比如:number),我们再次使用 Tyep 当做返回值类型,知道参数类型与返回值类型是相同的
平时开发时没必要手动使用<类型>
传,因为类型推论可以自动完成
如果编译器不能够自动地推断出类型的,才手动传入
默认值,像函数参数一样也可以赋上默认值
function foo<Type = string>(arg: Type): Type{
return arg
}
平常使用类型变量名的缩写:
- T : Type的缩写
- K : key的缩写
- V : value的缩写
- E : Element的缩写
- O : Object的缩写
泛型接口
在定义接口的时候我们也可以使用泛型
interface IFoo<T = number> {
id: T,
valueList: T[],
handleValue: (value: T) => void
}
const foo: IFoo<number> = {
id: 101,
valueList: [1,2,3]
handleValue: function(value: number){
console.log(value)
}
}
泛型类
泛型类与泛型接口差不多。 泛型类使用<>
括起泛型类型,跟在类名后面
class Point<T> {
x: T
y: T
constructor(x: T, y: T){
this.x = x
this.y = y
}
}
// 类型推论
const p1 = new Point(10,20)
// 明确
const p2 = new Point<number>(10,20)
const p3: Point<number> = new Point(10,20)
泛型约束(Generic Constraints)
希望传入的类型有某些共性,但是这些共性可能不是在同一种类型中
- 比如string和array都是有length的,或者某些对象也是会有length属性的
- 那么拥有length的属性都可以作为参数类型
interface ILength {
length: number
}
function foo<T extends ILength>(arg: T): T{
console.log(arg.length);
}
//泛型函数被定义了约束,不再是适用于任意类型
foo(123) // error
// 符合约束类型的值,必须包含必须的属性
foo({length: 10, value: 20})
在泛型约束中使用类型参数
举个栗子:我们希望获取一个对象给定属性名的值
- 我们需要确保我们不会获取 obj 上不存在的属性
- 所以我们在两个类型之间建立一个约束
// 声明Type类型参数,Key 类型参数继承 Type里的key
function foo<Type, Key extends Type keyof Type>(obj: Type, key: Key){
console.log(obj[key])
}
const info = {
name: 'kun'
age: 12
}
foo(info,"name")
foo(info,"age")
映射类型(Mapped Types)
一个类型需要基于另外一个类型,但你又不想拷贝一份,这个时候可以考虑使用映射类型。
- 大部分内置的工具都是通过映射类型来实现
- 大多数类型体操的题目也是通过映射类型完成
映射类型建立在索引签名上
- 映射类型,就是使用了 PropertyKeys 联合类型的泛型
- PropertyKeys 多是通过 keyof 创建,然后循环遍历
映射修饰符(Mapping Modifiers)interface IPerson { name: string age: number } type MapType<Type> = { [property in keyof Type]: any } type NewPerson = MapType<IPerson>
在使用映射类型时,有两个额外的修饰符可能会用到:
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{
console.log(arg+arg2)
}
参考资料
评论
匿名评论隐私政策
✅ 你无需删除空行,直接评论以获取最佳展示效果