泛型:宽泛的类型,其实就是类型的参数化,让类型像参数一样,不预先指定,而是在使用的时候再让别人传入进来。
在定义函数、类或者接口时,如果遇到类型不明确的时候,就可以使用泛型。
平常开发中可能会用到一些名称的缩写:
- T:Type 的缩写,类型。
- K、V:key 和 value 的缩写,键值对。
- E:Element 的缩写,元素。
- O:Object 的缩写,对象。
泛型函数:
定义函数时,在函数名的后面加上 <通用的任意命名的类型名称>
,然后再将类型定义为参数的类型;调用函数时,在函数名的后面加上 <具体的实际的类型名称>
。
例如:定义一个函数,参数接收什么,返回值就返回什么。
// 1. 没有给参数 args 定义类型,默认是 any
function fn (args) {
return args
}
// 2. 返回值的类型就也是 any。但这样其实就是没有做类型检测
const res1 = fn('Lee')
const res2 = fn(18)
// 3. 给参数 args 定义联合类型
function fn2 (args: string | number) {
return args
}
// 4. 返回值的类型就也是联合类型。但实际想要的结果是传入什么类型的参数,就返回什么类型的返回值
const res3 = fn2('Lee')
const res4 = fn2(18)
// 使用泛型来实现:
// 2. 接收类型
// 3. 将其定义为参数的类型
function fn3<argsType> (args: argsType) {
return args
}
// 1. 将类型传入
const res5 = fn3<string>('Lee')
const res6 = fn3<number>(18)
大部分情况,调用函数时,可以省略不传递类型,因为 TypeScript 会根据传递的参数进行类型推断。但是也有可能会推断错误,此时就需要手动传递类型了。
function fn<argsType> (args: argsType) {
return args
}
// 可以省略不传递类型,TypeScript 会根据传递的参数进行类型推断
let res1 = fn('Lee') // 使用 let 会推断出 string 类型
const res2 = fn(18) // 使用 cont 会直接推断成更加具体的字面量类型
泛型函数支持给类型指定默认值。
function fn<argsType = string> (args: argsType ) {
return args
}
let res = fn('Lee')
泛型函数支持传入多个泛型。
function fn<args1Type, args2Type> (args1: args1Type, args2: args2Type ) {
return {args1, args2}
}
const res = fn<string, number>('Lee', 18)
泛型类:
在定义类的时候也可以使用泛型。
定义类时,在类名的后面加上 <通用的任意命名的类型名称>
,然后再将类型定义为属性的类型;调用类时,在类名的后面加上 <具体的实际的类型名称>
。
class Point<Type> {
constructor(public x: Type, public y: Type) {}
}
const p1 = new Point<number>(10, 20)
const p2 = new Point<string>('10', '20')
大部分情况,调用类时,可以省略不传递类型,因为 TypeScript 会根据传递的参数进行类型推断。但是也有可能会推断错误,此时就需要手动传递类型了。
泛型类支持给类型指定默认值。
泛型类也支持传入多个泛型。
泛型接口:
在定义接口的时候也可以使用泛型。
定义接口时,在接口名的后面加上 <通用的任意命名的类型名称>
,然后再将类型定义为属性的类型;调用接口时,在接口名的后面加上 <具体的实际的类型名称>
。
interface PersonInterface<Type> {
name: Type,
age: number,
hobby: Type,
}
const p1: PersonInterface<string> = {
name: 'Lee',
age: 18,
hobby: '吃',
}
const p2: PersonInterface<boolean> = {
name: true,
age: 18,
hobby: false,
}
泛型接口中,TypeScript 无法进行类型推断,必须明确传递类型。除非指定默认值的话,就可以不明确传递类型了。
// 指定类型的默认值
interface PersonInterface<Type = string> {
name: Type,
age: number,
hobby: Type,
}
const p: PersonInterface = {
name: 'Lee',
age: 18,
hobby: '吃',
}
泛型接口也支持传入多个泛型。