[英]What's the difference between "declare class" and "interface" in TypeScript
In TypeScript, when creating.d.ts source declaration files, which is preferable and why?在 TypeScript 中,当创建 .d.ts 源声明文件时,哪个更好,为什么?
declare class Example {
public Method(): void;
}
or或者
interface Example {
Method(): void;
}
The differences that I can tell are that interfaces can't have static methods, so you must use a class for that.我可以说的区别是接口不能有 static 方法,所以你必须为此使用 class。 Both don't product any JS output, so perhaps it doesn't matter?
两者都不产生任何 JS output,所以也许没关系?
interface
is for when you simply want to describe the shape of an object. interface
适用于您只想描述对象的形状。 There's no code generation, ever, for interfaces -- they're solely an artifact in the type system. 对接口来说,没有代码生成 - 它们只是类型系统中的工件。 You'll see no difference in the code generation for a class depending on whether or not it has an
implements
clause. 您将看到类的代码生成没有区别,具体取决于它是否具有
implements
子句。
declare class
is for when you want to describe an existing class (usually a TypeScript class, but not always) that is going to be externally present (for example, you have two .ts files that compile to two .js files and both are included via script
tags in a webpage). declare class
用于描述当前要在外部存在的现有类(通常是TypeScript类,但并非总是如此)(例如,您有两个.ts文件,它们编译为两个.js文件,并且都包含在内通过网页中的script
标签)。 If you inherit from a class
using extends
(regardless of whether the base type was a declare class
or a regular class
) the compiler is going to generate all the code to hook up the prototype chain and forwarding constructors and what not. 如果从使用
extends
继承class
(无论基类型是declare class
还是常规class
),编译器将生成所有代码以连接原型链和转发构造函数,而不是。
If you try to inherit from a declare class
that should have been an interface, you are going to have a runtime error because that generated code will be referring to an object with no runtime manifestation. 如果您尝试从应该是接口的
declare class
继承,那么您将遇到运行时错误,因为生成的代码将引用没有运行时表现形式的对象。
Conversely, if you simply implement
an interface that should have been a declare class
, you're going to have to re-implement all the members yourself and won't be taking advantage of any code re-use from the would-be base class, and functions that check the prototype chain at runtime will reject your object as not actually being an instance of the base class. 相反,如果您只是
implement
一个应该是declare class
的接口,那么您将不得不自己重新实现所有成员,并且不会利用可能基类中的任何代码重用。 ,以及在运行时检查原型链的函数将拒绝您的对象,因为它实际上不是基类的实例。
To get really nerdy, if you have a C++ background, you can roughly think of interface
as typedef
and declare class
as an extern
declaration of a constructor that strictly lacks a definition in this compile unit. 为了得到真正的书呆子,如果你有C ++背景,你可以粗略地将
interface
视为typedef
并将declare class
声明为构造函数的extern
声明,该构造函数严格缺少此编译单元中的定义。
From a pure consumption side (writing imperative code, not adding new types), the only difference between interface
and declare class
is that you can't new
an interface. 从纯粹的消费方面(编写命令式代码,而不是添加新类型),
interface
和declare class
之间的唯一区别是你不能new
一个接口。 However, if you intend to extend
/ implement
one of these types in a new class
, you absolutely have to have chosen correctly between interface
and declare class
. 但是,如果您打算在新
class
extend
/ implement
其中一种类型,则必须在interface
和declare class
之间正确选择。 Only one of them will work. 只有其中一个可以工作。
Two rules that will serve you well: 两条规则将很好地为您服务:
new
) that's actually present at runtime (eg Date
is, but JQueryStatic
is not)? new
调用的东西)对齐(例如Date
是,但JQueryStatic
不是)? If no , you definitely want interface
interface
declare class
declare class
You can implement the interface: 您可以实现界面:
class MyClass implements Example {
Method() {
}
}
Whereas the declare class
syntax is really intended to be used to add type definitions for external code that isn't written in TypeScript - so the implementation is "elsewhere". 而
declare class
语法实际上是用于为不是用TypeScript编写的外部代码添加类型定义 - 因此实现是“其他地方”。
In layman's terms, declare
is used in .ts
/ d.ts
files to tell the compiler that we should expect the keyword we're declaring
to exist in that environment, even if it is not defined in the present file. 在外行人的术语中,
declare
在.ts
/ d.ts
文件中用于告诉编译器我们应该期望我们declaring
在该环境中存在的关键字,即使它没有在当前文件中定义。 This will then allow us to have type safety when using the declared object, as the Typescript compiler now knows that some other component may provide that variable. 这将允许我们在使用声明的对象时具有类型安全性,因为Typescript编译器现在知道某些其他组件可以提供该变量。
declare
and interface
in TS: declare
和interface
区别: declare: 宣布:
declare class Example {
public Method(): void;
}
In the above code declare
lets the TS compiler know that somewhere the class Example
is declared. 在上面的代码
declare
让TS编译器知道某个类的Example
被声明了。 This does not mean that the class is magically included. 这并不意味着该课程被神奇地包括在内。 You as a programmer are responsible for having the class available when you are declaring it (with the
declare
keyword). 作为程序员,您负责在声明它时使用该类(使用
declare
关键字)。
interface: 接口:
interface Example {
Method(): void;
}
An interface
is a virtual construct that only exists within typescript. interface
是仅存在于打字稿中的虚拟构造。 The typescript compiler uses it for the sole purpose of type checking. typescript编译器仅将其用于类型检查。 When the code is compiled to javascript this whole construct will be stripped out.
当代码编译为javascript时,整个构造将被剥离。 The typescript compiler uses interfaces in order to check if objects have the right structure.
typescript编译器使用接口来检查对象是否具有正确的结构。
For example when we have the following interface: 例如,当我们有以下界面时:
interface test {
foo: number,
bar: string,
}
The objects which we define which have this interface type need to match the interface exactly: 我们定义的具有此接口类型的对象需要与接口完全匹配:
// perfect match has all the properties with the right types, TS compiler will not complain.
const obj1: test = {
foo: 5,
bar: 'hey',
}
it just feels redundant!?只是觉得多余!?
I understand that I need a d.ts (declaration) file to make use of types outside of the project, but why not use the same declaration instead of an additional interface/type?我知道我需要一个 d.ts(声明)文件来使用项目之外的类型,但为什么不使用相同的声明而不是额外的接口/类型?
Then type and interface seems to be the same as well!?那么类型和界面似乎也一样!?
I've checked the typescript code (GitHub) and they use (it seems) type for one-ligner types and interfaces for objects with more properties...我已经检查了打字稿代码(GitHub),他们使用(似乎)类型来表示单一类型的类型和具有更多属性的对象的接口......
=> to me personally it feels like interfaces belong to classes and types to everything else, but that's just an assumption far from the origin topic ^^ => 就我个人而言,感觉接口属于类,类型属于其他一切,但这只是远离原始主题的假设 ^^
any enlightening is welcome, appreciating.欢迎任何启发,欣赏。
PS: do I only need a declaration file when my code is written in JS (to make it understood in typescript projects where I import the package?) I mean otherwise I could export types easily. PS:当我的代码是用 JS 编写时,我是否只需要一个声明文件(以便在我导入包的打字稿项目中理解它?)我的意思是否则我可以轻松导出类型。 maybe I get closer...?
也许我更接近...?
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.