泛型

函数泛型

函数名后跟一个尖括号<>,尖括号内部是动态类型参数(泛型)

1
2
3
4
5
6
7
function yajue<T>(a:T,b:T,c:T):Array<T> {
return [a,b,c]
}
// 调用时,可以指定泛型T的具体类型
console.log(yajue<number>(1,1,4))
// 当然也可以不指定,ts会推断类型的
console.log(yajue("money","violence","sex"))

也可以同时使用多个泛型,只要在数量和使用方式上能对应即可

1
2
3
4
function jueya<T,U>(a:T,b:U):Array<T|U> {
return [a,b]
}
jueya<Boolean,number>(false,1)

还可以给泛型指定默认值

1
2
3
4
5
function jueya<T = number>(a:T,b:T):Array<T> {
return [a,b]
}
// 什么都不传时,会被ts推断为默认值number
// jueya()

泛型别名

在type中可以使用泛型

1
2
3
4
5
6
7
type A<T> = string | number | T

let a:A<boolean>
a = false // ok
a = "omg" // ok
a = 114514 // ok
// a = {} // 不ok

泛型接口

泛型也可以用在接口上

1
2
3
4
5
6
7
8
9
interface Data<T> {
msg: T
}
let data1:Data<string> = {
msg: "yjsp"
}
let data2:Data<number> = {
msg: 114514
}

泛型类

1
2
3
4
5
6
7
8
9
10
11
12
13
14
class Sub<T>{
attr: T[] = [];
add (a:T):T[] {
return [a]
}
}

let s = new Sub<number>()
s.attr = [1,2,3]
s.add(123)

let str = new Sub<string>()
str.attr = ['1','2','3']
str.add('123')

泛型约束

期望在一个泛型的变量上面获取length参数

1
2
3
function getLegnth<T>(arg:T) {
return arg.length
}

但是,有些数据类型是没有length属性,这时就可以使用泛型约束,此处约束T为具有length属性的类型

1
2
3
4
5
6
7
8
9
interface Len {
length:number
}

function getLegnth<T extends Len>(arg:T) {
return arg.length
}

getLegnth<string>('123')

keyof约束对象

其中使用了TS泛型和泛型约束

  1. 首先,定义T类型,并使用extends关键字继承object类型的子类型
  2. 然后,使用keyof操作符获取T类型的所有键,它的返回类型是联合类型
  3. 最后,利用extends关键字约束K类型必须为keyof T联合类型的子类型
1
2
3
4
5
6
7
8
function prop<T extends object, K extends keyof T>(obj: T, key: K) {
return obj[key]
}

let o = { a: 1, b: 2, c: 3 }

prop(o, 'a')
prop(o, 'd') // 不ok

type中也可以这么用

1
2
3
4
5
6
7
8
9
10
11
type Options<T extends object> = {
[Key in keyof T]?:T[Key]
}

interface Data {
name:string,
age:number,
sex:string
}

type B = Options<Data>