泛型
可以理解为是动态类型,在定义函数时不明确类型,而是采用泛型(占位符),在使用时泛型会自动推断出相应类型。它主要是为了解决一些具有相同逻辑的函数但传入参数不同,而导致的代码逻辑重复性高的问题。
基本使用
函数泛型
function fun1<T>(a: T, b: T): Array<T> {
// <>定义泛型,里面可以随意
return [a, b];
}
fun1(1, 2); // fun1<number>(1,2) 写全是这样,但是ts能类型推断出来,所以可以不用写完整
fun1("1", "2");
fun1(false, true);
type 泛型
type A<T> = string | number | T;
let a: A<null> = null;
interface 泛型
interface B<T> {
msg: T;
}
let data: B<number> = {
msg: 1,
};
联合泛型
function add<T, K>(a: T, b: K): Array<T | K> {
return [a, b];
}
add(1, false);
泛型也可以设置默认值:
function add<T = number, K = number>(a: T, b: K): Array<T | K> { return [a, b]; }
应用
调用接口时使用泛型:
const axios = {
get<T>(url: string): Promise<T> {
return new Promise((resolve, reject) => {
let xhr: XMLHttpRequest = new XMLHttpRequest();
xhr.open("GET", url);
xhr.onreadystatechange = () => {
if (xhr.readyState == 4 && xhr.status == 200) {
resolve(JSON.parse(xhr.responseText));
}
};
xhr.send(null);
});
},
};
interface Data {
message: string;
code: number;
}
axios.get<Data>("./data.json").then((res) => {
console.log(res); // res能访问Data里定义的属性
});
泛型约束(extends,内有 keyof)
使用泛型约束来控制泛型的类型范围。通过再泛型的后面跟一个extends再跟一个约束的泛型类型来进行约束:
function add<T extends number>(a: T, b: T) {
return a + b;
}
add(1, 2); // 这样对于add()来说约束了参数相加的类型,避免了不能相加的类型
约束传入参数具有
length属性:interface Len { length: number; } function fun<T extends Len>(a: T) { a.length; } fun("dsadas"); fun([1, 2, 3]); // fun(123) 没有length,不支持 // fun(true) 没有length,不支持约束对象的 key:
约束传入的值为某个对象的属性。
let obj = { name: "张三", age: 18, }; function ob<T extends object, K extends keyof T>(obj: T, key: K) { return obj[key]; // 如果不对K进行约束,则key会报错 } ob(obj, "name");keyof:将对象类型里的 key 推断成联合类型。
type Key = keyof typeof obj; // type Key = "name" | "age"对对象类型里的 key(属性)添加可选 符号:
interface Data { name: string; age: number; sex: string; } type Options<T extends object> = { [Key in keyof T]?: T[Key]; // 定义一个Key(任意)使用in操作符再联合类型T中循环 }; type B = Options<Data>;