本文已参与「新人创作礼」活动,一起开启掘金创作之路。
泛型介绍(个人理解非官方)
泛型:可指广泛未知的类型,也就是说可以是多种不同的类型,比如可以是number,string,boolean,数组(Array),元组(Tuple)枚举(enum)等等类型。。。。
泛型示例(1)
function identity<T>(arg: T): T {
return arg;
}
我们为此函数添加了类型变量T,也就是<T>,此时T会捕捉调用函数时传入的参数类型比如
identity("字符串")
此时我们传入了“字符串”, <T> 会捕捉到参数类型为字符串然后将类型给形参arg,此时arg的类型也为string,返回值也应为string,这是一个较为经典的泛型例子,往下看.
identity<number>("字符串")
此时调用identity函数时限制了类型为<number>,传入"字符串"会提示参数类型报错"
假如我们修改一下identity函数
function identity<T>(arg: T): T {
console.log(arg.length) // 会提示类型“T”上不存在属性“length”。
return arg;
}
解决报错方案(1)
此时参数类型应该传入一个数组
function identity<T>(arg: T[]): T[] {
console.log(arg.length) // 2
return arg;
}
identity(["参数1","参数2"])
此时我们可以为identity函数添加限制类型
identity<string>(["参数1","参数2"]) // success
identity<number>(["参数1","参数2"]) // error
在限制类型为number时,数组中的参数类型应全部为number, 此时<T>指的是数组中每个元素的类型而不是指数组类型
解决报错方案(2)
// 定义一个接口
interface Lengthwise {
length: number;
}
// T继承Lengthwise接口,使得T拥有length属性
function identity<T extends Lengthwise>(arg: T): T {
console.log(arg.length)
return arg;
}
// 调用identity函数
identity([1,2]) // success 数组本身就有length属性所以不会报错
identity({length: 1, value: 3}) // success
在泛型约束中使用类型参数(官网例子会报错)
function getProperty(obj: T, key: K) {
return obj[key];
}
let x = { a: 1, b: 2, c: 3, d: 4 };
getProperty(x, "a"); // okay
getProperty(x, "m"); // error: Argument of type 'm' isn't assignable to 'a' | 'b' | 'c' | 'd'.
// 官网例子会提示找不到T,K,我们加上TK之后
function getProperty<T,K>(obj: T, key: K) {
return obj[key]; // 提示类型“K”无法用于索引类型“T”。
}
经过一番尝试后还是不行只好求助于百度,Google等(毕竟面向百度编程)
// 将官网例子改为
function getProperty<T, K extends keyof T>(obj: T, key: K) {
return obj[key];
}
getProperty(x, "a"); // okay
getProperty(x, "m"); // error: Argument of type 'm' isn't assignable to 'a' | 'b' | 'c' | 'd'.\
// 如上 `K extends keyof T` 的含义为,key 只能是在 obj 当中存在的属性,如果指定的 key 在 obj 当中不存在就不允许获取