TypeScript中"声明类"和"接口"之间的区别是什么

Chr*_*ris 98 javascript typescript

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

declare class Example {
    public Method(): void; 
}
Run Code Online (Sandbox Code Playgroud)

要么

interface Example {
    Method(): void;
}
Run Code Online (Sandbox Code Playgroud)

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

Rya*_*ugh 149

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

declare class是为了描述一个现有的类(通常是一个TypeScript类,但并不总是),它将在外部存在(例如,你有两个.ts文件可以编译为两个.js文件,并且两者都是通过script标签包含的在网页中).如果继承自classusing extends(无论基类型是a declare class还是常规class),编译器将生成所有代码以连接原型链和转发构造函数,而不是.

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

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

为了得到真正的书呆子,如果你有一个C++背景,你可以大致认为interfaceas typedef和一个构造函数declare classextern声明严格缺少这个编译单元中的定义.

从纯粹的消费侧(写入必要的代码,而不是增加新的类型),之间的唯一区别interface,并declare class是,你不能new一个接口.但是,如果你打算在一个新的extend/ implement这些类型中的一个class,你绝对必须在interface和之间正确选择declare class.只有其中一个可以工作.

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

  • 类型的名称是否与new在运行时实际存在的构造函数(可调用的东西)对齐(例如Date是,但JQueryStatic不是)?如果不是,你绝对想要interface
  • 我是在处理来自另一个TypeScript文件的编译类,还是类似的东西?如果,请使用declare class

  • 您不能在接口类型上调用`new`运算符.但是,接口可以具有构造签名,这意味着您可以在接口类型的值上调用`new`运算符.这与`class`的工作方式非常不同,其中构造签名在类型名称本身而不是在该类型的表达式上. (3认同)

Fen*_*ton 23

您可以实现界面:

class MyClass implements Example {
    Method() {

    }
}
Run Code Online (Sandbox Code Playgroud)

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


nik*_*ong 11

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


Wil*_*een 7

TSdeclareinterfaceTS之间的区别:

宣布:

declare class Example {
    public Method(): void; 
}
Run Code Online (Sandbox Code Playgroud)

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

界面:

interface Example {
    Method(): void;
}
Run Code Online (Sandbox Code Playgroud)

Aninterface是一种仅存在于打字稿中的虚拟结构。打字稿编译器仅将其用于类型检查。当代码被编译为 javascript 时,整个构造将被剥离。typescript 编译器使用接口来检查对象是否具有正确的结构。

例如,当我们有以下界面时:

interface test {
  foo: number,
  bar: string,
}
Run Code Online (Sandbox Code Playgroud)

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

// perfect match has all the properties with the right types, TS compiler will not complain.
  const obj1: test = {   
    foo: 5,
    bar: 'hey',
  }
Run Code Online (Sandbox Code Playgroud)