在TypeScript中,当创建.d.ts源代码声明文件时,哪一个更可取,为什么?
declare class Example { public Method(): void; }
或者是
interface Example { Method(): void; }
我能说的区别是接口不能有静态方法,所以你必须使用一个类。两者都不产生任何JS输出,所以也许这并不重要?
bybem2ql1#
interface用于当您只想描述对象的形状时。从来没有为接口生成代码--它们只是类型系统中的一个工件。您不会看到类是否具有implements子句在代码生成方面的差异。declare class用于当你想要描述一个 * 现有 * 类(通常是一个TypeScript类,但并不总是),它将在外部存在(例如,你有两个.ts文件,编译成两个.js文件,两者都通过script标签包含在网页中)。如果你使用extends从class继承(不管基类型是declare class还是常规的class),编译器将生成所有代码来连接原型链和转发构造函数等等。如果你试图从一个应该是接口的declare class继承,你将遇到一个运行时错误,因为生成的代码将引用一个没有运行时表现的对象。相反,如果你只是implement一个应该是declare class的接口,你将不得不自己重新实现所有的成员,并且不会利用任何来自基类的代码重用,并且在运行时检查原型链的函数将拒绝你的对象,因为它实际上不是基类的示例。如果你有一个C++背景,你可以粗略地认为interface是typedef,declare class是一个构造函数的extern声明,在这个编译单元中严格缺乏定义。从纯粹的消费Angular (编写命令式代码,而不是添加新类型)来看,interface和declare class之间的唯一区别是不能new接口。但是,如果您打算在新的class中使用extend/implement,则必须在interface和declare class之间正确选择。只有一个能用。有两条规则对你很有用:
interface
implements
declare class
script
extends
class
implement
typedef
extern
new
extend
Date
JQueryStatic
xn1cxnb42#
您可以实现接口:
class MyClass implements Example { Method() { } }
而declare class语法实际上是用来为不是用TypeScript编写的外部代码添加类型定义的--所以实现是“在别处”。
n6lpvg4x3#
通俗地说,declare在.ts/d.ts文件中用于告诉编译器我们应该期望关键字we are declaring存在于该环境中,即使它没有在当前文件中定义。这将允许我们在使用声明的对象时具有类型安全性,因为Typescript编译器现在知道其他一些组件可能提供该变量。
declare
.ts
d.ts
declaring
vpfxa7rd4#
声明:
在上面的代码中,declare让TS编译器知道在某个地方声明了类Example。这并不意味着类被神奇地包含在内。作为一名程序员,您有责任在声明类时(使用declare关键字)确保该类可用。
Example
接口:
interface是只存在于typescript中的虚拟构造。类型脚本编译器使用它的唯一目的是类型检查。当代码被编译成javascript时,整个结构将被剥离。类型脚本编译器使用接口来检查对象是否具有正确的结构。例如,当我们有以下接口时:
interface test { foo: number, bar: string, }
我们定义的具有此接口类型的对象需要与接口完全匹配:
// perfect match has all the properties with the right types, TS compiler will not complain. const obj1: test = { foo: 5, bar: 'hey', }
4条答案
按热度按时间bybem2ql1#
interface
用于当您只想描述对象的形状时。从来没有为接口生成代码--它们只是类型系统中的一个工件。您不会看到类是否具有implements
子句在代码生成方面的差异。declare class
用于当你想要描述一个 * 现有 * 类(通常是一个TypeScript类,但并不总是),它将在外部存在(例如,你有两个.ts文件,编译成两个.js文件,两者都通过script
标签包含在网页中)。如果你使用extends
从class
继承(不管基类型是declare class
还是常规的class
),编译器将生成所有代码来连接原型链和转发构造函数等等。如果你试图从一个应该是接口的
declare class
继承,你将遇到一个运行时错误,因为生成的代码将引用一个没有运行时表现的对象。相反,如果你只是
implement
一个应该是declare class
的接口,你将不得不自己重新实现所有的成员,并且不会利用任何来自基类的代码重用,并且在运行时检查原型链的函数将拒绝你的对象,因为它实际上不是基类的示例。如果你有一个C++背景,你可以粗略地认为
interface
是typedef
,declare class
是一个构造函数的extern
声明,在这个编译单元中严格缺乏定义。从纯粹的消费Angular (编写命令式代码,而不是添加新类型)来看,
interface
和declare class
之间的唯一区别是不能new
接口。但是,如果您打算在新的class
中使用extend
/implement
,则必须在interface
和declare class
之间正确选择。只有一个能用。有两条规则对你很有用:
new
调用的东西)对齐的类型的名称(例如Date
是,但JQueryStatic
不是)?如果 * 否 *,则肯定需要interface
declare class
xn1cxnb42#
您可以实现接口:
而
declare class
语法实际上是用来为不是用TypeScript编写的外部代码添加类型定义的--所以实现是“在别处”。n6lpvg4x3#
通俗地说,
declare
在.ts
/d.ts
文件中用于告诉编译器我们应该期望关键字we aredeclaring
存在于该环境中,即使它没有在当前文件中定义。这将允许我们在使用声明的对象时具有类型安全性,因为Typescript编译器现在知道其他一些组件可能提供该变量。vpfxa7rd4#
TS中
declare
和interface
的区别:声明:
在上面的代码中,
declare
让TS编译器知道在某个地方声明了类Example
。这并不意味着类被神奇地包含在内。作为一名程序员,您有责任在声明类时(使用declare
关键字)确保该类可用。接口:
interface
是只存在于typescript中的虚拟构造。类型脚本编译器使用它的唯一目的是类型检查。当代码被编译成javascript时,整个结构将被剥离。类型脚本编译器使用接口来检查对象是否具有正确的结构。例如,当我们有以下接口时:
我们定义的具有此接口类型的对象需要与接口完全匹配: