泛型
泛型用在函数中,类似函数的形参,可以在调用时当作实参传递过来
//定义一个函数,并通过 <> 接收一个类型 T
// T 类型便可以像变量一样使用在其他地方
// 比如 val的类型、函数的返回值类型
function getValue<T>(val: T):T {
return val;
}
//将 string类型用<>传入函数中,此时函数的T类型为string
const name = getValue<string>("小王");
//将 number类型用<>传入函数中,此时函数的T类型为number
const age = getValue<number>(34);
之前看到TS会做类型推断,也就是说,即使不显式的传、,函数也可以知道 "小王“ 是string类型、34 是number类型,并将对应的类型传入T类型。
但有人试过,自己写的函数,TS的类型推断竟如下
function getValue<T>(val: T) {
return val;
}
//T类型为 ”小王“
const name = getValue("小王");
//T类型为 34
const age = getValue(34);
这时候name的类型只能为 ”小王“ 类型,如果变为 小李,就会类型报错。
这是因为用了const声明的常量,所以本身就不可以改变值,此时换成let声明就可以了。有人用了let也不可以,那就传类型过去吧。
keyof 、 extends 与 联合类型
keyof : 作用是获取对象类型的key,并变为联合类型
联合类型 : 就是多个类型,符合其中一个即可, string | number | boolean
extends : 继承,可以让 一个类型继承另一个类型
//定义一个Person类型
interface Person {
name: string;
age: number;
}
//使用 keyof 获取 Person 类型的键,并赋值给类型 K
// 此时 K 的 类型为 "name" | "age"
// 之所以是 字符串类型的 “name” 和 “age”
// 是因为 对象的键就是 string类型的
type K = keyof Person;
//接收泛型 T 并继承 类型Person
//将形参val限制类型为 T
//将形参key限制类型为 K
function getValue<T extends Person>(val: T, key: K) {
//由于 K 符合 Person的键,所以可以动态读取值
return val[key];
}
//将第一个参数传递为对象,并包含 name和age属性
const name = getValue(
{
name: "小王",
age: 34,
gender:"male"
},
//第二个值由于类型为 Person 的键的联合类型
//所以必须是“name” 或 “age”
"name"
);
const age = getValue(
{
name: "小王",
age: 34,
gender:"male"
},
"age"
);
当然,上面的返回值类型就是Person类型的值类型,就是 string | number。
如果想要更准确的类型,也可以用泛型传入。