泛型简单介绍
-
泛型是什么
泛型指的是在定义函数/接口/类型时,不预先指定具体的类型,而是在使用的时候指定类型限制的一种特性
-
泛型的意义(目的)
设计泛型的关键目的是在成员之间提供有意义的约束。
这些成员可以是:类的实例成员、类的方法、函数参数和函数返回值。
泛型的使用
泛型的写法就是在标志符后面添加尖括号(<>),然后在尖括号里写形参,并在 body(函数体, 接口体或类体) 里用这些形参做一些逻辑处理。
1. 在函数中使用泛型
//添加类型变量T,T帮助我们捕获用户传入的类型(比如:number)
//参数类型为T,返回值类型为T
function fun1<T>(x: T): T {
return x;
}
//这里传入T为string类型
fun1<string>('a')
//这里传入T为number类型
fun1<number>(123)
2. 接口中使用泛型
首先是ts接口写法
interface IInfo {
name: string
age?: number // 可选类型
}
const info: IInfo = {
name: 'james',
age: 20
}
info.age // ok
info.name // ok
在接口中使用到泛型的写法
// 可以同时传入多个类型
interface User<T, N> {
name: T,
age: N
}
const user: User<string, number> = {
name: 'hsh',
age: 18
}
user.name // ok
user.age // ok
3. 在类中使用泛型
在类中使用泛型也很简单,我们只需要在类名后面,使用 <T, …> 的语法定义任意多个类型变量
interface GenericInterface<U> {
value: U
getIdentity: () => U
}
class IdentityClass<T> implements GenericInterface<T> {
value: T
constructor(value: T) {
this.value = value
}
getIdentity(): T {
return this.value
}
}
const myNumberClass = new IdentityClass<Number>(68);
console.log(myNumberClass.getIdentity()); // 68
const myStringClass = new IdentityClass<string>("Semlinker!");
console.log(myStringClass.getIdentity()); // Semlinker!
implements
也是实现父类和子类之间继承关系的关键字,如类 A 继承 类 B 写成 class A implements B{}.
implements是一个类实现一个接口用的关键字,他是用来实现接口中定义的抽象方法。
比如:people是一个接口,他里面有say这个方法。public interface people(){ public say();}但是接口没有方法体。
只能通过一个具体的类去实现其中的方法体。比如chinese这个类,就实现了people这个接口。
public class chinese implements people{ public say() {System.out.println(“你好!”);}}
接下来以实例化 myNumberClass 为例,来分析一下其调用过程:
在实例化 IdentityClass 对象时,我们传入 Number 类型和构造函数参数值 68;
之后在 IdentityClass 类中,类型变量 T 的值变成 Number 类型;
IdentityClass 类实现了 GenericInterface<T>
,而此时 T 表示 Number 类型,因此等价于该类实现了 GenericInterface<Number>
接口;
而对于 GenericInterface<U>
接口来说,类型变量 U 也变成了 Number。
这里我有意使用不同的变量名,以表明类型值沿链向上传播,且与变量名无关。
泛型类可确保在整个类中一致地使用指定的数据类型。
泛型约束
使用接口约束泛型
interface Person {
name:string;
age:number;
}
function student<T extends Person>(arg:T):T {
return arg;
}
student({name:'lili'});//类型 "{ name: string; }" 中缺少属性 "age",但类型 "Person" 中需要该属性
student({ name: "lili" , age:'11'});//不能将类型“string”分配给类型“number”
student({ name: "lili" , age:11});