当前位置: 首页 > 知识库问答 >
问题:

何时在TypeScript库中使用类与接口?

红经亘
2023-03-14

我见过类似这样的相关问题,但它们都假设类和接口的区别在于类可以实例化,而接口不能。然而,以@types/google.maps为例,例如:

declare namespace google.maps {
  class Map extends google.maps.MVCObject {
    constructor(mapDiv: HTMLElement, opts?: google.maps.MapOptions);
    controls: google.maps.MVCArray<any>[];
    data: google.maps.Data;
    fitBounds(
        bounds: google.maps.LatLngBounds|google.maps.LatLngBoundsLiteral,
        padding?: number|google.maps.Padding): void;
    // ...
  }
}
declare namespace google.maps {
  interface MapType {
    alt: string|null;
    getTile(
        tileCoord: google.maps.Point|null, zoom: number,
        ownerDocument: Document|null): Element|null;
    maxZoom: number;
    minZoom: number;
    name: string|null;
    projection: google.maps.Projection|null;
    radius: number;
    releaseTile(tile: Element|null): void;
    tileSize: google.maps.Size|null;
  }
}
declare namespace google.maps {
  interface MapTypeControlOptions {
    mapTypeIds?: (string)[]|null;
    position?: google.maps.ControlPosition|null;
    style?: google.maps.MapTypeControlStyle|null;
  }
}
declare namespace google.maps {
  class MapTypeRegistry extends google.maps.MVCObject {
    set(id: string, mapType: any): void;
  }
}
declare namespace google.maps {
  interface MapsEventListener {
    remove(): void;
  }
}
declare namespace google.maps {
  interface WebglCameraParams extends google.maps.CameraParams {
    lat: number;
    lng: number;
  }
}

接口和类:

  • 延伸其他对象
  • 具有属性
  • 具有方法/功能
  • 无法从这些定义直接实例化

在google maps代码中的某个地方,实际上有一个类用于这里定义的< code >类和这里定义的< code >接口。看起来类定义是用户可以实例化的,而不是库可以内部实例化的(接口)。

那么,在这些上下文中,接口和类之间更深层次的区别是什么?我明白另一个答案是什么,类通常是可构造的,但是这些类显然不是直接可实例化的。它们代表其他类。但是接口也代表其他类。所以我很困惑。

共有1个答案

拓拔俊德
2023-03-14

(来自您的评论):

我在问他们为什么把它们定义为类而不是接口。

< code>type 、< code>interface和< code>class之间有重叠(你很清楚这一点,但我必须从某个地方开始:-)),但是< code>class做三件事,而不只是< code>interface或< code>type会做的一件事。让我们看一个更简单的例子:

declare namespace example1 {
    class Example1 {
        a: string;
        constructor(a: string);
        static method(): void;
    }
}

那:

  • 定义描述实例的类型 Example1
  • 定义存在一个运行时绑定 Example1,该绑定引用这些实例的构造函数。(它不会创建绑定,它只是说有一个绑定。
  • 隐式)定义一个类型(类型示例 1),该类型是构造函数的类型。

如果您想在没有class的情况下编写相同的东西,您必须自己编写这三个东西中的每一个,例如示例2here:

declare namespace example2 {
    // Define the type for instances
    interface Example2 {
        a: string;
    }
    // Define that there is a binding for the constructor function
    let Example2: {                 //
        new (a: string): Example2;  // Define the type for the constructor function
        method(): void;             //
    };                              //
}

您甚至可以更进一步,为构造函数声明一个命名类型:

declare namespace example3 {
    // Define the type for instances
    interface Example3 {
        a: string;
    }
    // Define the type for the constructor function
    interface Example3Constructor {
        new (a: string): Example3;
        method(): void;
    }
    // Define that there is a binding for the constructor function
    let Example3: Example3Constructor;
}

(这就是<code>lib.es5.d.ts</code>所做的,比如<code>数组</code>,除了它使用<code>var</code>而不是<code>let</code>。)

和往常一样,当有不止一种方法做某事时,有些人会用一种方法做,有些人会用另一种方法做,但是当class同时描述你试图描述的所有部分时,使用它有一些论点。

 类似资料: