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
标签)。 如果使用extends
inheritanceclass
(不pipe基类是declare class
还是常规class
),编译器将生成所有代码来连接原型链和转发构造函数,而不是。
如果你尝试从一个应该是一个接口的declare class
inheritance,那么你将会遇到一个运行时错误,因为这个生成的代码将会引用一个没有运行时间performance的对象。
相反,如果你只是简单地implement
一个应该是一个declare class
的接口,那么你将不得不自己重新实现所有的成员,并且不会利用从可能的基类中的任何代码重用,并且在运行时检查原型链的函数将会拒绝你的对象,因为实际上并不是基类的一个实例。
如果你有一个C ++的背景,你可以粗略地将interface
看作是typedef
并把declare class
声明为一个构造方法的extern
声明,这个构造方法在这个编译单元中严格地缺less一个定义。
从纯粹的消费方面(编写命令性的代码,而不是添加新的types), interface
和declare class
的唯一区别就是你不能new
一个接口。 但是,如果您打算在新class
extend
/ implement
这些types之一,则必须在interface
和declare 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。