泛型约束就是对入参值的属性进行一个约束
interface Class{
name:string,
age:number
}
function result<T extends Class>(val:T):T {
console.log(val.name)
return val
}
result({name:"zhangsan",age:10})
//如果参数重不写age的话,就会报错
//类型“{ name: string; }”的参数不能赋给类型“Class”的参数。
//类型 "{ name: string; }" 中缺少属性 "age",但类型 "Class" 中需要该属性。
result({name:"zhangsan"})
这里的 T extends Class就是class中继承的写法如下
class BaseClass {
public value:string;
constructor() {
this.value = "899879";
}
baseMethod(): void {
console.log("Base method called.");
}
}
// 继承基类
class DerivedClass extends BaseClass {
derivedMethod(): void {
console.log("Derived method called.");
}
}
// 创建一个派生类的实例
const instance = new DerivedClass();
// 调用派生类的方法
console.log(instance.value) 输出: '899879'
instance.derivedMethod(); // 输出: 'Derived method called.'
// 调用基类的方法
instance.baseMethod(); // 输出: 'Base method called.'
相当于在BaseClass类中定义了一个对象和方法。
class BaseClass {
value: "899879";
baseMethod() {}
}
DerivedClass类继承后也有了这个属性和方法
class DerivedClass {
value: "899879";
baseMethod() {}
}
这里我们抛去方法不谈,有点像如下的结构
const A = {
name: "zhangsan",
age: 10}
const B extends A {
}
extends后B就有东西了
const B = {
name: "zhangsan",
age: 10
}
瞎扯的代码,没有这么个写法,就是帮助前端理解class和extends的
可以这么理解
B : {name:"zhagnsan",
age:10}
回到我们最开始的泛型约束,T extends Class后就有了
T : {
name:string,
age:number
}
这里的T作为一个入参类型,那么入参val是一个{key:value,key:value}的结构
那么就顺理成章的有val.key的出现,就是 val.name
当入参是一个字符串的时候 a = ‘fawegawg’
通过泛型约束对于a,它就应该有a.name或者a.age的影藏属性
interface MyLength {length:number}
// 创建泛型函数
function add<type extends MyLength>(value: type): type{
console.log(value.length)
return value
}
add([1,2])
add('123')
add({name:'张三',length:12,age:13})
这里的第一个入参arr就有.length属性,第二个,第三个都有.length属性。
个人感觉用实例化的方法可以达到使用extends实现泛型约束的效果
class Box<T> {
public value: T;
constructor(value: T) {
this.value = value;
}
getValue(): T {
return this.value;
}
}
let box1 = new Box<number>(42);
console.log(box1.getValue(),box1.value); // 输出:42
let box2 = new Box<string>("Hello");
console.log(box2.getValue()); // 输出:Hello
new了之后也出现了类似如下的结构
box1:{
value:42
}