泛型

更新时间: 2023-03-02 11:16:25

# 泛型

泛型可以理解为类型的形参,T是一个标识符,可以自定义,T表示某种类型

function fn1<T,G>(n:T,m:G):Array<T|G> {
  return [n,m]
}
fn1<number,string>(100,"1")
fn1<boolean,number>(true,1)
fn1<'hello','world'>('hello','world')
1
2
3
4
5
6

# 泛型定义类型别名

type StrOrNum = string|number
//type ObjType = {name:string,getName:() => string}
type ObjType<N,G=number> = {name:N,getName:() => G}

let obj:ObjType<StrOrNum> = {
    name:"",
    getName(){
        return 1
    }
}
1
2
3
4
5
6
7
8
9
10

# 泛型定义接口

// 泛型 - 接口
// interface PersonItf {
//     name:string,
//     getName:() => string
// }
// 可以设置默认的类型,在使用的时候就可以省略不传
interface PersonItf<N,G=string> {
    name:N,
    getName:() => G
}

let obj2:PersonItf<StrOrNum,StrOrNum> = {
    name:"",
    getName:() => {
        return ""
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17

# 对象字面量泛型

let foo:{<T>(arg:T):T}

foo = function<T>(arg:T):T {
  return arg
}

foo(123)
1
2
3
4
5
6
7

# 泛型约束

我们期望在一个泛型的变量上面,获取其length参数,但是,有的数据类型是没有length属性的,于是我们就可以使用类型约束,约束其为具有length属性的类型

interface Len {
  length:number
}

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

getLength<string>('123')
1
2
3
4
5
6
7
8
9

# 使用keyof约束对象

其中使用了TS泛型和泛型约束。首先定义了T类型并使用extends关键字继承object类型的子类型,然后使用keyof操作符获取T类型的所有键,它的返回 类型是联合 类型,最后利用extends关键字约束 K类型必须为keyof T联合类型的子类型

function prop<T,K extends keyof T>(obj:T,key:K) {
    return obj[key]
}

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

prop(o,'a')

//prop(0,'d') 报错
1
2
3
4
5
6
7
8
9

# 泛型类

声明方法跟函数类似名称后面定义<类型> 使用的时候确定类型new Sub<number>()

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')
1
2
3
4
5
6
7
8
9
10
11
12
13
14