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

2022-08-30 04:27:05

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

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

interface Example {
    Method(): void;
}

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


答案 1

interface是用于当您只想描述对象的形状时。对于接口来说,从来没有代码生成 - 它们只是类型系统中的工件。在类的代码生成中,您不会看到任何差异,具体取决于它是否具有子句。implements

declare class当您想要描述将存在于外部的现有类(通常是TypeScript类,但并非总是如此)时(例如,您有两个编译为两个.js文件并且两个文件都通过网页中的标记包含在内)。。如果你从一个 using 继承(不管基类型是 a 还是一个常规类型),编译器将生成所有代码来挂接原型链和转发构造函数等等。scriptclassextendsdeclare classclass

如果尝试从本应是接口的 继承,则会出现运行时错误,因为生成的代码将引用没有运行时表现形式的对象。declare class

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

为了真正成为书,如果你有一个C++背景,你可以粗略地把它想象成一个构造函数的声明,在这个编译单元中严格缺乏定义。interfacetypedefdeclare classextern

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

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

  • 类型的名称是否与构造函数(可调用的)对齐,该构造函数实际上存在于运行时(例如 是,但不是)?如果不是,你肯定想要newDateJQueryStaticinterface
  • 我是否正在处理来自另一个TypeScript文件的已编译类,或者足够相似的东西?如果,请使用declare class

答案 2

您可以实现该接口:

class MyClass implements Example {
    Method() {

    }
}

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