TypeScript中的“声明类”和“接口”有什么区别?

在TypeScript中,当创build.d.ts源代码声明文件,这是可取的,为什么?

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

要么

 interface Example { Method(): void; } 

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

interface是当你只是想描述一个对象的形状。 对于接口,没有代码生成 – 它们只是types系统中的一个工件。 你会发现一个类的代码生成没有区别,取决于它是否有一个implements子句。

declare class是为了当你想要描述一个现存的类(通常是一个TypeScript类,但并不总是),这个类将会在外部存在(例如,你有两个.ts文件可以编译成两个.js文件,并且都包含在内通过网页中的script标签)。 如果使用extendsinheritanceclass (不pipe基类是declare class还是常规class ),编译器将生成所有代码来连接原型链和转发构造函数,而不是。

如果你尝试从一个应该是一个接口的declare classinheritance,那么你将会遇到一个运行时错误,因为这个生成的代码将会引用一个没有运行时间performance的对象。

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

如果你有一个C ++的背景,你可以粗略地将interface看作是typedef并把declare class声明为一个构造方法的extern声明,这个构造方法在这个编译单元中严格地缺less一个定义。

从纯粹的消费方面(编写命令性的代码,而不是添加新的types), interfacedeclare class的唯一区别就是你不能new一个接口。 但是,如果您打算在新class extend / implement这些types之一,则必须在interfacedeclare class之间正确select。 其中只有一个会工作。

两个规则,将为您服务:

  • 是types的名称与构造函数(实际上是在运行时可以调用的东西(如Date是,但JQueryStatic不是))? 如果不是 ,你一定要interface
  • 我是从另一个TypeScript文件处理编译的类,或者是类似的东西吗? 如果 ,则使用declare class

你可以实现这个接口:

 class MyClass implements Example { Method() { } } 

declare class语法实际上是用来为不是用TypeScript编写的外部代码添加types定义 – 所以实现是“别处”。

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