TypeScript - 接口扩展



在 TypeScript 中,接口是定义对象形状和强制类型约束的强大方法。它们允许我们指定对象必须具有的必需属性和方法。接口的一个有趣特性是能够扩展它们,允许我们创建接口的组合。扩展接口也称为接口继承

接口继承允许您创建更专业的接口,这些接口继承自其他接口的属性和方法。

语法

使用extends关键字在 TypeScript 中扩展单个或多个接口。

interface NewInterface extends ExistingInterface {
   // Additional properties and methods
}

interface NewInterface extends Interface1, Interface2, ... {
   // Additional properties and methods
}

上面显示了通过扩展现有接口创建新接口的语法。还显示了扩展多个接口的语法。第二个语法是扩展多个接口。

扩展单个接口

我们可以通过扩展单个接口来实现单接口继承。让我们从一个简单的场景开始,在这个场景中,我们有一个名为 Shape 的接口,它为各种形状定义了一个公共属性 color。我们希望创建一个名为 ColoredShape 的新接口,它扩展 Shape 并添加一个额外的属性 name。

示例

让我们看看扩展 Shape 接口以创建 ColoredShape 接口的示例。在此示例中,我们定义了具有 color 属性的 Shape 接口。然后,我们通过扩展 Shape 并添加 name 属性创建了 ColoredShape 接口。我们实例化了一个类型为 ColoredShape 的对象 square,并为 color 和 name 属性赋值。最后,我们使用点表示法访问并打印了 color 和 name 的值。

interface Shape {
   color: string;
}

interface ColoredShape extends Shape {
   name: string;
}

const square: ColoredShape = {
   color: "red",
   name: "Square",
};

console.log(square.color);
console.log(square.name); 

编译后,它将生成以下 JavaScript 代码

var square = {
   color: "red",
   name: "Square"
};
console.log(square.color);
console.log(square.name);

输出

red
Square

扩展多个接口

在 TypeScript 中,我们还可以扩展多个接口以创建一个新的接口,该接口组合来自所有扩展接口的属性和方法。这使我们能够通过重用现有接口来创建更复杂和更专业的接口。这有助于在 TypeScript 中实现多接口继承。

示例

在下面的示例中,我们定义了 Printable 和 Scanable 接口,每个接口都有其各自的方法。然后,我们通过扩展 Printable 和 Scanable 接口并添加新的方法 copy() 创建了 MultifunctionalDevice 接口。我们在名为 Printer 的类中实现了 MultifunctionalDevice 接口,并为所有方法提供了必要的实现。最后,我们实例化了 Printer 类的对象并调用了 print()、scan() 和 copy() 方法。

interface Printable {
   print(): void;
}

interface Scanable {
   scan(): void;
}

interface MultifunctionalDevice extends Printable, Scanable {
   copy(): void;
}

class Printer implements MultifunctionalDevice {
   print() {
      console.log("Printing...");
   }

   scan() {
      console.log("Scanning...");
   }

   copy() {
      console.log("Copying...");
   }
}

const printer = new Printer();
printer.print(); 
printer.scan(); 
printer.copy(); 

编译后,它将生成以下 JavaScript 代码

var Printer = /** @class */ (function () {
   function Printer() {
   }
   Printer.prototype.print = function () {
      console.log("Printing...");
   };
   Printer.prototype.scan = function () {
      console.log("Scanning...");
   };
   Printer.prototype.copy = function () {
      console.log("Copying...");
   };
   return Printer;
}());
var printer = new Printer();
printer.print();
printer.scan();
printer.copy();

输出

Printing...
Scanning...
Copying...

增强现有接口

我们可能经常遇到想要通过添加其他属性或方法来增强现有接口的情况。扩展接口允许我们这样做,而无需直接修改原始接口。

示例

在此示例中,我们有一个具有 name 属性的现有 User 接口。我们扩展 User 接口以创建 EnhancedUser 接口,该接口添加了 age 属性和 greet() 方法。通过扩展接口,我们可以定义类型为 EnhancedUser 的对象 user,其中包含来自两个接口的属性和方法。

interface User {
   name: string;
}

interface EnhancedUser extends User {
   age: number;
   greet(): void;
}

const user: EnhancedUser = {
   name: "John Wick",
   age: 25,
   greet() {
      console.log(`Hello, my name is ${this.name} and I'm ${this.age} years old.`);
   }
};

user.greet();

编译后,它将生成以下 JavaScript 代码

var user = {
   name: "John Wick",
   age: 25,
   greet: function () {
      console.log("Hello, my name is ".concat(this.name, " and I'm ").concat(this.age, " years old."));
   }
};
user.greet();

输出

Hello, my name is John Wick and I'm 25 years old.

创建组合接口

在创建组合接口时,扩展接口也可能很有价值,这些接口组合来自多个源的属性和方法。当使用提供其接口的外部库或模块时,这尤其有用。

示例

在此示例中,我们有四个接口:Product、DiscountedProduct、ProductWithReviews 和 FeaturedProduct。每个接口都扩展了一个或多个现有接口,允许我们创建一个具有来自多个源的属性和方法的组合接口。然后,我们定义一个类型为 FeaturedProduct 的对象 product,其中包含在扩展接口中定义的所有属性。

interface Product {
   name: string;
   price: number;
}

interface DiscountedProduct extends Product {
   discount: number;
}

interface ProductWithReviews extends Product {
   reviews: string[];
}

interface FeaturedProduct extends DiscountedProduct, ProductWithReviews {
   featured: boolean;
}

const product: FeaturedProduct = {
   name: "Smartphone",
   price: 599,
   discount: 50,
   reviews: ["Great product!", "Highly recommended."],
   featured: true
};

console.log(product.featured); 
console.log(product.reviews);

编译后,它将生成以下 JavaScript 代码

var product = {
   name: "Smartphone",
   price: 599,
   discount: 50,
   reviews: ["Great product!", "Highly recommended."],
   featured: true
};
console.log(product.featured);
console.log(product.reviews);

输出

true
[ 'Great product!', 'Highly recommended.' ]

覆盖属性和方法

在扩展接口时,我们还可以覆盖从基接口继承的属性和方法。这使我们能够修改或为扩展接口中的特定属性或方法提供不同的实现。

示例

在下面的示例中,我们有一个具有 name 属性和 makeSound() 方法的 Animal 接口。我们扩展 Animal 接口以创建 Dog 接口。通过覆盖 Dog 接口中的 makeSound() 方法,我们提供了特定于狗的不同实现。然后可以实例化类型为 Dog 的对象 dog,并且在调用时将调用覆盖的方法。

interface Animal {
   name: string;
   makeSound(): void;
}

interface Dog extends Animal {
   makeSound(): void;
}

const dog: Dog = {
   name: "Buddy",
   makeSound() {
      console.log("Woof woof!");
   }
};

dog.makeSound();

编译后,它将生成以下 JavaScript 代码

var dog = {
   name: "Buddy",
   makeSound: function () {
      console.log("Woof woof!");
   }
};
dog.makeSound();

输出

Woof woof!
广告