131

在 TypeScript 中,当创建 .d.ts 源声明文件时,哪个更可取,为什么?

declare class Example {
    public Method(): void; 
}

或者

interface Example {
    Method(): void;
}

我可以说的区别是接口不能有静态方法,所以你必须为此使用一个类。两者都不产生任何 JS 输出,所以也许没关系?

4

4 回答 4

180

interface当您只想描述对象的形状时。从来没有为接口生成代码——它们只是类型系统中的一个工件。取决于它是否具有implements子句,您将看到类的代码生成没有区别。

declare class用于描述将在外部存在的现有类(通常是 TypeScript 类,但并非总是如此)时(例如,您有两个 .ts 文件,它们编译为两个 .js 文件,并且都通过script标签包含在内在网页中)。如果您从classusing继承extends(无论基类型是 adeclare class还是常规class),编译器将生成所有代码以连接原型链和转发构造函数等等。

如果您尝试从declare class应该是接口的继承,您将遇到运行时错误,因为生成的代码将引用没有运行时表现的对象。

相反,如果您只是implement一个应该是 a 的接口declare class,您将不得不自己重新实现所有成员,并且不会利用来自可能的基类和函数的任何代码重用在运行时检查原型链将拒绝您的对象,因为它实际上不是基类的实例。

如果你有 C++ 的背景,你可以粗略地认为是interfacetypedef作为declare class一个extern构造函数的声明,该构造函数在此编译单元中严格缺乏定义。

interface从纯粹的消费端(编写命令式代码,不添加新类型)来看,和之间的唯一区别declare class是你不能new使用接口。但是,如果您打算extend/implement其中一种类型在 newclass中,您绝对必须在interface和之间正确选择declare class。只有其中一个会起作用。

两条规则会很好地为您服务:

  • new类型的名称是否与运行时实际存在的构造函数(可调用的东西)对齐(例如Date,是,但JQueryStatic不是)?如果没有,你肯定想要interface
  • 我是在处理来自另一个 TypeScript 文件的编译类,还是类似的东西?如果,请使用declare class
于 2013-01-15T22:27:16.760 回答
27

您可以实现接口:

class MyClass implements Example {
    Method() {

    }
}

而该declare class语法实际上旨在用于为不是用 TypeScript 编写的外部代码添加类型定义 - 所以实现是“其他地方”。

于 2013-01-15T20:38:13.343 回答
15

通俗地说,declare.ts/ d.tsfiles 中用于告诉编译器我们应该期望我们将declaring存在于那个环境中的关键字,即使它没有在当前文件中定义。这将允许我们在使用声明的对象时具有类型安全性,因为 Typescript 编译器现在知道其他一些组件可能会提供该变量。

于 2016-04-19T21:05:07.373 回答
7

TS之间的declare区别:interface

宣布:

declare class Example {
    public Method(): void; 
}

在上面的代码中declare,让 TS 编译器知道在某处Example声明了类。这并不意味着该类被神奇地包含在内。作为程序员,您有责任在声明该类时(使用declare关键字)使该类可用。

界面:

interface Example {
    Method(): void;
}

Aninterface是仅存在于 typescript 中的虚拟构造。typescript 编译器将它用于类型检查的唯一目的。当代码编译为 javascript 时,整个结构将被删除。typescript 编译器使用接口来检查对象是否具有正确的结构。

例如当我们有以下接口时:

interface test {
  foo: number,
  bar: string,
}

我们定义的具有这种接口类型的对象需要与接口完全匹配:

// perfect match has all the properties with the right types, TS compiler will not complain.
  const obj1: test = {   
    foo: 5,
    bar: 'hey',
  }
于 2018-11-21T14:22:22.333 回答