接口

接口运行时的影响为 0。TypeScript 接口中有很多方式来声明变量的结构。

以下两个是等效声明, 第一个使用内联注解,第二个使用接口:

  1. // Sample A
  2. declare const myPoint: { x: number; y: number };
  3. // Sample B
  4. interface Point {
  5. x: number;
  6. y: number;
  7. }
  8. declare const myPoint: Point;

示例 B 的好处在于,如果有人创建了一个基于 myPoint 的库来添加新成员, 他们可以轻松将此成员添加到 myPoint 的现有声明中:

  1. // Lib a.d.ts
  2. interface Point {
  3. x: number,
  4. y: number
  5. }
  6. declare const myPoint: Point
  7. // Lib b.d.ts
  8. interface Point {
  9. z: number
  10. }
  11. // Your code
  12. let myPoint.z // Allowed!

因为 TypeScript 接口是开放式的,这是 TypeScript 的一个重要原则,它允许你使用接口模仿 JavaScript 的可扩展性。

类可以实现接口

如果你希望在类中使用必须遵循的接口(类)或是别人定义的对象结构,可以使用 implements 关键字来确保兼容性:

  1. interface Point {
  2. x: number;
  3. y: number;
  4. }
  5. class MyPoint implements Point {
  6. x: number;
  7. y: number; // Same as Point
  8. }

基本上在 implements(实现) 的存在下,该外部 Point 接口的任何更改都将导致代码库中的编译错误,因此可以轻松地使其保持同步:

  1. interface Point {
  2. x: number;
  3. y: number;
  4. z: number; // New member
  5. }
  6. class MyPoint implements Point {
  7. // ERROR : missing member `z`
  8. x: number;
  9. y: number;
  10. }

注意,implements 限制了类实例的结构,即:

  1. let foo: Point = new MyPoint();

foo: Point = MyPoint 这样并不是一回事。

注意

并非每个接口都是很容易实现的

接口旨在声明 JavaScript 中可能存在的任意结构。

思考以下例子,其中可以使用 new 调用某些内容:

  1. interface Crazy {
  2. new (): {
  3. hello: number;
  4. };
  5. }

你可能会有这样的代码:

  1. class CrazyClass implements Crazy {
  2. constructor() {
  3. return { hello: 123 };
  4. }
  5. }
  6. // Because
  7. const crazy = new CrazyClass(); // crazy would be { hello:123 }

你可以使用接口声明所有的 JavaScript,甚至可以安全地从 TypeScript 中使用它们。但并不意味着你可以使用 TypeScript 类来实现它们。

原文: https://jkchao.github.io/typescript-book-chinese/typings/interfaces.html