一. 什么叫泛型?
在函数定义时, 不确定参数是什么类型, 使用泛型后, 在函数调用时指定类型
// <T> 定义泛型
// val: T 使用泛型
function getVal<T>(val: T): T {
return val
}
getVal<string>('123')
二. 泛型约束
使用泛型后, 在函数未调用时, 函数本身并不知道即将传入的是什么类型, 所以在函数内部使用使用了泛型的参数时, 无法直接使用对应类型的方法或属性 (如图)
解决方案:
- 1.使用条件语句进行类型收缩(书写较麻烦)
function getVal3<T>(val: T) { if(typeof val === 'string') { console.log(val.length) } return val } getVal3('123456') - 2.添加约束 利用接口
interface ILength { length: number } // (Type extends 接口) 添加泛型约束 // 表示传入的类型必须满足 ILength 接口的要求 function getVal4<T extends ILength>(val: T) { console.log(val.length) return val } getVal4('123456')
三. 多个泛型 与 keyof
现有需求 定义一个函数, 传入一个对象 和 一个字符串属性名, 返回属性值, 但是ts不确定能不能在obj对象中找到name属性, 就会报错 (如图)
keyof 关键字: 限制必须是某个对象的属性
解决方法:
// K extends keyof O 表示必须是 O 的属性
function getProp1<O, K extends keyof O>(obj: O, key: K) {
return obj[key]
}
getProp1({name: '小丽'}, 'name')
当传入字符串不是obj对象属性的时候就会报错 (如图):
keyof 其他用法
type Person = {
name: string,
age: number,
hobby: string
}
let p1: keyof Person = 'age' //表示只能是Person中的属性
四. 泛型接口
可以在接口中使用泛型, Array<string> 使用的就是泛型接口
interface Students<T> {
id: number
name: T
hobby: T[]
}
let stu:Students<string> = {
id: 1,
name: '小美',
hobby: [
'篮球',
'音乐'
]
}
console.log(stu)