泛型的理解
简单的理解
ts中的泛型就跟any差不多,不过与any不同的是,any会丢失类型而泛型不会。
比如使用any时:
function fx(s: any): any{
return s + ''
}
// 当中fx传入一个 num 10 但是最后返回回来的参数可能是 string ,这样对于参数类型就会丢失。
使用泛型时:
function fx<T>(s: T): T{
return s + ''
}
// 这时候泛型回存储传入参数的类型,使得返回时的类型与之相同,当fx传入一个num 10 最后就会报错,因为返回的时string
实际应用
泛型接口的应用
function identity<T>(arg: T): T{
return arg
}
interface GenericIdentityFn<T>{
(arg: T): T
}
let myIdentity: GenericIdentityFn<number> = identity // 定义泛型类型为number
泛型类
class GenericNumber<T> {
value: T
add: (x: T, y: T) => T
}
let myGenericNumber = new GenericNumber<number>()
// myGenericNumber.value = '' // 报错,因为传入的是 string
myGenericNumber.value = 0
myGenericNumber.add = function(x, y){
return x + y
}
console.log(myGenericNumber.add(myGenericNumber.value, 1))
let stringGeneric = new GenericNumber<string>()
stringGeneric.value = ''
stringGeneric.add = function(x, y){
return x + y
}
console.log(stringGeneric.add(stringGeneric.value, 'test'))
泛型约束
在某些时候,我们传入的值可能没有一些属性,在使用泛型时就会报错,比如:
function length<T>(nums: T): T{
console.log(nums.length) // 如果传入的是一个数字,而数字没有长度,则会报错
return nums
}
这时,就需要我们给泛型添加一个约束:
interface Lengthwise {
length: number;
}
function length<T extends Lengthwise>(nums: T): T{
console.log(nums.length)
return nums
}
length(5) // 如果是个数字,就会约束类型,并且报错
length({length: 1}) // 参数有length,则不会报错
还有在某些时候,我们可能会有一些其他的需求,需要查询对象中的某个值
function getProperty<T,K extends keyof T>(obj: T, key: K){
return obj[key]
}
let x = {
a: 1,
b: 2,
c: 3,
d: 4
}
getProperty(x, 'a')
getProperty(x, 'm') // 报错,因为m不再x当中
泛型中使用类类型
function fx<T>(c : { new(): T}): T{
return new c()
}
还不太懂