TS extends深入解析:从继承到约束再到分配
2023-07-27 13:31:49
** extends 的世界:继承、约束和分配的艺术**
在 TypeScript 的广阔天地中,extends 扮演着变幻莫测的角色,它可以代表继承、约束和分配等多种含义。让我们一起踏上奇妙的探索之旅,揭开 extends 关键字的面纱,领略它在不同场景下的独特风采。
1. 继承:血脉相传的艺术
extends 关键字最负盛名的用法莫过于继承,它赋予你创造一个新类的能力,这个新类继承自另一个现有的类,拥有其属性和方法。就像搭积木一样,你可以通过 extends 复用代码,让新类继承父类的大部分特性。
class Animal {
name: string;
constructor(name: string) {
this.name = name;
}
speak() {
console.log(`My name is ${this.name}`);
}
}
class Dog extends Animal {
bark() {
console.log(`Woof! My name is ${this.name}`);
}
}
const dog = new Dog('Buddy');
dog.speak(); // My name is Buddy
dog.bark(); // Woof! My name is Buddy
在这个例子中,Dog 类继承了 Animal 类,它不仅拥有 Animal 类的 name 属性和 speak() 方法,还新增了一个 bark() 方法,从而形成了一个更加具体的子类。
2. 约束:形状和定义的利器
extends 关键字不仅仅是继承的工具,它还可以作为一种约束条件,用于定义接口或类型别名的形状。通过 extends ,你可以指定一个类型必须满足某些要求,从而确保代码的安全性。
interface Shape {
area(): number;
}
class Circle implements Shape {
radius: number;
constructor(radius: number) {
this.radius = radius;
}
area() {
return Math.PI * this.radius ** 2;
}
}
class Square implements Shape {
sideLength: number;
constructor(sideLength: number) {
this.sideLength = sideLength;
}
area() {
return this.sideLength ** 2;
}
}
function calculateTotalArea(shapes: Shape[]): number {
let totalArea = 0;
for (const shape of shapes) {
totalArea += shape.area();
}
return totalArea;
}
const shapes = [new Circle(5), new Square(10)];
const totalArea = calculateTotalArea(shapes);
console.log(`Total area: ${totalArea}`); // Total area: 314.1592653589793
在这个例子中,Shape 接口定义了一个名为 area() 的方法,要求所有实现它的类都必须提供一个计算面积的方法。Circle 和 Square 类都实现了这个接口,并提供了自己的 area() 方法。
函数 calculateTotalArea() 使用 Shape 类型的数组作为参数,并计算这些形状的总面积。由于 Shape 接口确保了所有实现它的类都具有 area() 方法,因此函数可以放心地调用这个方法来计算面积。
3. 分配:兼容性的奥秘
extends 关键字的第三种用法是分配,它允许你将一个类型的变量分配给另一个类型的变量,前提是这两个类型是兼容的。兼容性是指,目标类型的形状必须包含或等于源类型的形状。
interface Animal {
name: string;
}
interface Dog extends Animal {
bark(): void;
}
const dog: Dog = {
name: 'Buddy',
bark() {
console.log(`Woof! My name is Buddy`);
}
};
const animal: Animal = dog; // Assignment is allowed because Dog is compatible with Animal
animal.name; // 'Buddy'
// animal.bark(); // Error: Property 'bark' does not exist on type 'Animal'
在这个例子中,Dog 接口继承了 Animal 接口,因此 Dog 类型的值是 Animal 类型的子集。这意味着你可以将一个 Dog 类型的变量分配给一个 Animal 类型的变量,因为 Dog 拥有 Animal 所要求的所有属性。
需要注意的是,分配只能发生在兼容的类型之间。如果目标类型的形状不包含源类型的形状,那么分配将失败。
结语
extends 关键字是 TypeScript 中一个功能强大的工具,它可以用于继承、约束和分配。通过灵活运用 extends 关键字,你可以构建更加灵活、健壮和可扩展的 TypeScript 代码。
常见问题解答
-
什么是 extends 关键字?
extends 关键字允许你创建一个新类或类型,该类或类型继承自另一个现有的类或类型。
-
继承是如何工作的?
继承允许子类获得父类的属性和方法,同时还可以定义自己的属性和方法。
-
约束是如何使用的?
约束用于指定一个类型必须满足某些要求。这有助于确保代码的安全性,因为编译器将检查类型是否满足这些要求。
-
分配是如何工作的?
分配允许你将一个类型的变量分配给另一个类型的变量,前提是这两个类型是兼容的。兼容性意味着目标类型的形状必须包含或等于源类型的形状。
-
如何使用 extends 关键字来实现接口?
extends 关键字可以用来实现一个接口,这意味着创建一个类或类型,该类或类型实现了接口中定义的所有方法。