如何扩展接口以创建接口组合?


在 TypeScript 中,接口提供了一种强大的方法来定义对象的形状并强制执行类型约束。它们允许我们指定对象必须具有的必需属性和方法。接口的一个有趣特性是扩展它们的能力,这允许我们创建接口的组合。在本教程中,我们将探讨如何扩展接口以创建继承现有接口的属性和方法的新接口。

语法

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

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

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

示例 1:扩展单个接口

让我们从一个简单的场景开始,在这个场景中,我们有一个名为 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

示例 2:扩展多个接口

在 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...

示例 3:增强现有接口

我们经常会遇到想要通过添加其他属性或方法来增强现有接口的情况。扩展接口允许我们这样做,而无需直接修改原始接口。在这个例子中,我们有一个带有 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.

示例 4:创建组合接口

在创建组合接口时,扩展接口也可能很有价值,组合接口组合来自多个源的属性和方法。当使用提供其接口的外部库或模块时,这尤其有用。在这个例子中,我们有四个接口: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.' ]

示例 5:覆盖属性和方法

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

在下面的示例中,我们有一个 Animal 接口,它具有 name 属性和 makeSound() 方法。我们扩展 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!

结论

总之,在 TypeScript 中扩展接口提供了一种强大的机制,用于创建接口组合、增强现有接口和促进代码可重用性。通过扩展接口,我们可以继承基接口的属性和方法,添加其他属性和方法,覆盖现有属性和方法,以及组合来自多个源的接口。

此功能允许我们构建灵活且强大的类型系统,使我们能够定义组件之间的清晰契约并强制执行类型安全。它增强了我们代码库的模块化、可读性和可维护性,使我们更容易管理和扩展应用程序。无论是扩展单个接口、组合多个接口、增强现有接口还是覆盖属性和方法,扩展接口的能力都使开发人员能够创建富有表现力和可重用的代码。

更新于:2023年8月21日

246 次浏览

启动您的 职业生涯

通过完成课程获得认证

开始
广告
© . All rights reserved.