问题描述
在 TypeScript 中,创建 .d.ts 源声明文件时,哪个更可取,为什么?
In TypeScript, when creating .d.ts source declaration files, which is preferable and why?
declare class Example {
public Method(): void;
}
或
interface Example {
Method(): void;
}
我能说的区别是接口不能有静态方法,所以你必须为此使用一个类.两者都不产生任何 JS 输出,所以也许这无关紧要?
The differences that I can tell are that interfaces can't have static methods, so you must use a class for that. Both don't product any JS output, so perhaps it doesn't matter?
推荐答案
interface
适用于您只想描述对象形状的情况.从来没有接口的代码生成——它们只是类型系统中的一个工件.根据类是否具有 implements
子句,您将看到它的代码生成没有区别.
interface
is for when you simply want to describe the shape of an object. 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.
declare class
用于描述一个现有 类(通常是一个 TypeScript 类,但不总是),该类将在外部出现(例如,您有两个 .ts 文件可以编译为两个 .js 文件,并且都通过网页中的 script
标签包含在内).如果您使用 extends
从 class
继承(无论基类型是 declare class
还是常规的 class
>) 编译器将生成所有代码以连接原型链和转发构造函数以及其他什么.
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). 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.
如果您尝试从一个应该是接口的声明类
继承,您将遇到运行时错误,因为生成的代码将引用一个没有运行时表现形式的对象.
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.
相反,如果您只是实现
一个应该是声明类
的接口,您将不得不自己重新实现所有成员并且不会'不要利用潜在基类中的任何代码重用,并且在运行时检查原型链的函数将拒绝您的对象,因为它实际上不是基类的实例.
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.
说真的,如果你有 C++ 背景,你可以粗略地把 interface
想象成 typedef
并将 declare class
想象成一个 extern
构造函数的声明,该构造函数在此编译单元中严格缺少定义.
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.
从纯粹的消费端(编写命令式代码,不添加新类型)来看,interface
和 declare class
的唯一区别是你不能新
一个界面.然而,如果你打算在一个新的 class
中extend
/implement
这些类型之一,你绝对必须在 之间做出正确的选择接口
和声明类
.只有其中一个会起作用.
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. 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
. Only one of them will work.
两条对您有用的规则:
- 类型的名称是否与运行时实际存在的构造函数(可使用
new
调用的东西)对齐(例如Date
是,但JQueryStatic
不是)?如果没有,你肯定想要interface
- 我是在处理来自另一个 TypeScript 文件的编译类,还是非常相似的东西?如果是,使用
declare class
- Is the name of the type aligning with a constructor function (something invokable with
new
) that's actually present at runtime (e.g.Date
is, butJQueryStatic
is not)? If no, you definitely wantinterface
- Am I dealing with a compiled class from another TypeScript file, or something sufficiently similar? If yes, use
declare class
这篇关于“声明类"和“声明类"有什么区别?和“界面"在打字稿中的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!