泛型
原创大约 2 分钟
泛型类和接口
将类和接口定义为泛型,类的成员变量和方法可以适应不同的类型,接口也可以适用于不同类型。
// 声明泛型类
class CustomStack<T> {
value: T | undefined;
setValue(val: T): void {
this.value = val;
}
getValue(): T | undefined {
return this.value;
}
}
let s = new CustomStack<string>();
s.setValue("hello");
// 输出"hello"
console.log(s.getValue());
interface GenericInterface<T> {
doSomething(value: T): void;
}
// 使用时指定类型
class ImplementingClass implements GenericInterface<string> {
doSomething(value: string): void {
console.log(value);
}
}
let is = new ImplementingClass();
// 输出"lixingyun"
is.doSomething("lixingyun");
泛型约束
可以通过参数对泛型进行约束,使之符合某些特定的属性和方法。
interface HasLength {
length: number;
}
// 被约束为特定类型
function logLength<T extends HasLength>(arg: T): void {
console.log(arg.length);
}
// 正确,因为字符串有length属性
// 输出9
logLength("lixingyun");
// 错误,数字没有length属性
// 输出undefined
logLength(10);
泛型函数
可以使用泛型参数来表示函数输入参数和返回值的类型,编写更通用的代码。
// 多个泛型参数,泛型数组
function last<T>(x: T[]): T {
return x[x.length - 1];
}
// 输出"bb"
console.log(last<string>(["aa", "bb"]));
// 显式设置的类型实参,输出3
console.log(last<number>([1, 2, 3]));
// 输出5
console.log(last([1, 2, 5]));
泛型默认值
泛型参数可以设置默认值,这样就可以不指定实际的类型实参,而只使用泛型类型名称。
class SomeType {}
interface Interface <T1 = SomeType> {}
class Base <T2 = SomeType> {}
// Derived1等价于Derived2
class Derived1 extends Base implements Interface {}
class Derived2 extends Base<SomeType> implements Interface<SomeType> {}
function foo<T = number>(): void {
console.log("lixingyun");
}
// 此函数等价于下面的调用
// 输出"lixingyun"
foo();
// 输出"lixingyun"
foo<number>();
感谢支持
更多内容,请移步《超级个体》。