TS(四) 泛型
1、什么是泛型
在定义这个函数时, 我不决定这些参数的类型,
而是让调用者以参数的形式告知,我这里的函数参数应该是什么类型
function sum<Type>(num: Type): Type {
console.log(num);
return num
}
// 1.调用方式一: 明确的传入类型
sum<number>(20)
sum<{ name: string }>({ name: "why" })
sum<any[]>(["abc"])
// 2.调用方式二: 类型推到
sum(50)
sum("abc")
2、定义多个泛型
function foo<T, E, O>(arg1: T, arg2: E, arg3?: O, ...args: T[]) {
console.log(arg1, arg2, arg3, args);
}
foo<number, string, boolean>(10, "abc", true)
3、泛型_接口的使用
定义接口的时,也可以使用泛型
// T1 = string 是默认值
interface IPerson<T1 = string, T2 = number> {
name: T1
age: T2
}
const p: IPerson<string,number> = {
name: "why",
age: 18
}
注意:接口内如果有函数,那么泛型需要定义在接口上,而不是定义在函数上
// 导入axios封装的类型
import type { AxiosRequestConfig, AxiosResponse } from 'axios'
// 泛型定义在这里
export interface HYRequestInterceptors<T = AxiosResponse> {
requestInterceptor?: (config: AxiosRequestConfig) => AxiosRequestConfig
requestInterceptorCatch?: (error: unknown) => unknown
// T必须来源于接口上
responseInterceptor?: (res: T) => T
responseInterceptorCatch?: (error: unknown) => unknown
}
export interface HYRequestConfig extends AxiosRequestConfig {
interceptors?: HYRequestInterceptors
showLoading?: boolean
}
4、泛型_类的使用
编写类时也可以使用泛型
class Point<T> {
x: T
y: T
z: T
constructor(x: T, y: T, z: T) {
this.x = x
this.y = y
this.z = y
}
}
const p1 = new Point("1.33.2", "2.22.3", "4.22.1")
const p2 = new Point<string>("1.33.2", "2.22.3", "4.22.1")
const p3: Point<string> = new Point("1.33.2", "2.22.3", "4.22.1")
// 以下两种写法等价
const names1: string[] = ["abc", "cba", "nba"]
const names2: Array<string> = ["abc", "cba", "nba"] // 不推荐(react jsx <>)
5、泛型约束
Question:有时候我们希望传入的类型有某些共性,但是这些共性可能不是在同一种类型中:
比如string和array都是有length的,或者某些对象也是会有length属性的; 那么只要是拥有length的属性都可以作为我们的参数类型,那么应该如何操作呢?
interface ILength {
length: number
}
//拥有length属性的值才能传进来
// 通过extends进行限制
function getLength<T extends ILength>(arg: T) {
console.log(arg.length);
return arg.length
}
getLength("abc")
getLength(["abc", "cba"])
getLength({ length: 100 })