1.背景
范型是静态类型语言的基本特征,typescript中的范型在开发中的函数、类型、类、接口中使用比较广泛。、
2.范型的语法
< T >, 其中T表示传入的类型,所以< T >就表示T类型的范型。也就是说,你可以将T看作一个类型参数,在构建的时候只是一个占位符,但是在使用的时候会有具体值的标签,类似于函数的参数。
3.范型的基本使用
3.1 范型在函数中的使用
范型的使用场景有很多,举一个最简单的例子:我们希望从对象中获取一些属性构建新的对象,例如:
const obj = {
name: '',
age: '',
company: ''
}
// 此时我们需要构建一个函数功能,实现输入一个keys数组,就能从对象中拿出在keys数组中的值
function getKeys(obj, keysArr) {
//
}
// 此时我们需要给obj和keysArr添加类型,一般来说我们给obj使用的是接口类型,但是obj现在是不定属性的,如果我们简单这么写的话:
interface personObj {
name: ''
age: ''
company: ''
}
function getKeys(obj: personObj, keysArr: string[]) {
const result: any = {}
keysArr.forEach((key: string) => {
if (key in obj) {
result[key] = obj[key]
}
})
}
此时,lint就会报以上的错误:元素隐式具有“任何”类型,因为“字符串”类型的表达式不能用于索引类型“personObj”。在类型“personObj”上找不到参数类型为“string”的索引签名。这也就是说,如果我们的字符串类型要想作为对象的key值的话,仅仅定义一个字符串类型是很弱的。所以我们必须要说明这个类型在对象的属性类型中。
对于这种情况,有两种解决方式,一种是使用:key as keyof typeof obj,但是这种在函数内部出现一次就要使用一次断言。
第二中解决方案就是使用范型,如下:
function pickObjectKeys<T, K extends keyof T>(obj: T, keys: K) {
return obj[keys]
}
// 也就是说T是我们定义的一个类型,而K是我们定义的另一个类型参数,K和T之间关系是,K是T的属性集合的子集。
// 但是我们如果这么写 K keyof T是错误的,因为K是一个类型,我们要使用keyof定义一个类型,一种是通过type K = keyof T,另一种就是继承。这里keyof T就意味着是"name" | "age" | "location"联合类型,而K是联合类型的子集。
interface Person {
name: string;
age: number;
location: string;
}
type K1 = keyof Person; // "name" | "age" | "location"
type K2 = keyof Person[]; // number | "length" | "push" | "concat" | ...
type K3 = keyof { [x: string]: Person }; // string | number
注意: keyof Obj产生的是联合类型,一般是keyof接口类型,或者keyof typeof 对象 这是范型使用比较常见的:1.限制键的输入类型 场景2: 分配通用参数
function getValue(value) {
return value
}
// TS
function getValue<T>(value: T): T{
return value
}
// 1.先是在函数名后面定义泛型类型参数 T
// 2.T类型的使用:参数定义类型 & 返回值类型
// 在使用的时候可以由Ts隐士推断,或者显示定义
const result = getValue(123);
const result = getValue<number>(123) // 此时getValue<number>('123')将报错
所以,看见函数中使用T的时候就立马反应出: 1.首先这是一个范型类型 2.然后看函数使用的时候这个范型的具体值 3.最后反应出这个类型限制了哪些变量,即哪些变量是被定义为这个范型具体值 例如,我看见function getValue< T >(value: T) T,立马知道了函数名后面定义了一个范型,其次通过范型的使用地方知道了函数参数和函数的返回值的类型限制,最后通过函数使用getValue< number >(123),知道了这个T就是number类型,那么原来的函数定义可以理解为:
function getValue<T = number>(value: number): number{
return value
}