“export declare class Actions”中的“declare”有啥作用?
Posted
技术标签:
【中文标题】“export declare class Actions”中的“declare”有啥作用?【英文标题】:What does 'declare' do in 'export declare class Actions'?“export declare class Actions”中的“declare”有什么作用? 【发布时间】:2016-05-03 09:05:42 【问题描述】:为什么我们需要在语句中使用declare
?
export declare class Actions
...
【问题讨论】:
Whats the difference between "declare class" and "interface" in TypeScript的可能重复 【参考方案1】:
declare
在打字稿中:
typescript 中的 declare
关键字有助于告诉 typescript 编译器 声明 是在其他地方定义的(在外部 javascript 文件或运行时环境的一部分中编写的地方)。
假设我们在其他地方声明了一个名为 foo 的变量。当我们尝试引用该变量时,打字稿编译器会抛出一个错误:
foo = 'random'; // Error: 'foo' is not defined
我们可以使用declare
关键字来解决这个问题:
declare var foo: string;
foo = 'random'; // no error anymore
这会产生以下后果:
当foo
实际上没有在其他任何地方声明,并且我们尝试使用该变量时,可能会发生运行时错误。因此,仅当您知道该变量此时可用时才使用 declare
关键字。
因为我们知道类型,所以我们(可能)可以访问我们的 IDE Intellisense。
因为我们知道类型,所以 typescript 编译器可以在编译时检查类型,如果我们在某些场景中使用了错误的类型,它会警告我们。
【讨论】:
【参考方案2】:在这种特定情况下的 declare 关键字:
export declare class Actions
...
... 显然没用,我认为 TypeScript 应该考虑将其作为错误(我不知道是否有隐藏的原因)。如果你声明一个类,你永远不需要导入它。如果您导出一个期望有人导入它的类,则不需要声明它。并且因为您正在声明此类,根据定义,此类应该无需导入即可使用。但是,当您export declare 一个类时,情况并非如此。您需要导入才能使用。
TL;DR
export declare class Actions
...
和
一样declare class Actions
...
【讨论】:
我觉得它们不一样,前者需要和import
一起使用,后者不需要
另外,声明不会破坏 .d.ts 文件的全局范围,而 export 会...(声明不会使文件成为模块)【参考方案3】:
declare
- 没有任何导入或导出关键字 - 定义由 TypeScript 自动选择的声明文件,这是向遗留模块添加类型的有用功能(没有 TypeScript 定义的 npm 安装包)。
import
/ export
是使用模块的正确方法,所有内容都需要手动(我觉得有点乏味)导入,要么是逻辑,要么是定义。
作为一个实际用例,export declare
允许您避免导出所有子元素,例如:
export declare namespace Redux
namespace Store
interface Definition ...
这可能比以下内容更容易阅读:
export namespace Redux
export namespace Store
export interface Definition ...
两种情况下的外部导入都是相同的(例如import Redux from 'definitions/redux';
),我不知道这是否是好的做法,但我觉得它很整洁! ^^
请务必记住,向文件添加 import
或 export
会将其提升为模块,因此 declare
范围将不再处于全局级别。
PS,有一个错误(issue 16671):如果您在声明中使用const enum
(我为redux 操作类型这样做)并且您指定了transpileOnly
标志(create-react- app-typescript 包确实如此,这就是我知道的原因),枚举不会被内联!你可以跑进去,也可以不跑,但提前知道很有用!
【讨论】:
模块中的命名空间export namespace
是 not a good idea 并添加 needless namespacing。关于export declare
,看看André Pena 的回答。【参考方案4】:
要理解这一点,首先要理解“declare”关键字。
这是来自Gil Fink's Blog的一个很好的解释:
TypeScript 声明关键字用于声明可能不是源自 TypeScript 文件的变量。
例如,假设我们有一个名为 myLibrary 的库,它没有 TypeScript 声明文件,并且在全局命名空间中有一个名为 myLibrary 的命名空间。如果您想在 TypeScript 代码中使用该库,可以使用以下代码:
declare var myLibrary;
TypeScript 运行时将赋予 myLibrary 变量的类型是 any 类型。这里的问题是您在设计时不会为该变量提供 Intellisense,但您将能够在代码中使用该库。在不使用 declare 关键字的情况下具有相同行为的另一种选择是仅使用具有 any 类型的变量:
var myLibrary: any;
两个代码示例将产生相同的 JavaScript 输出,但 declare 示例更具可读性并且表达了环境声明。
所以在你理解了“declare”关键字之后,回到你找到的地方
export declare class Action
...
该类的真正实现可能在其他地方——可能是一个 .js 文件。
【讨论】:
“两个代码示例将产生相同的 JavaScript 输出”,这是不正确的:declare var myLibrary
将转译为空:typescriptlang.org/play/#code/…
@Terrance Gil Flink 博客的链接对我不起作用(建立数据库连接时出错)。我认为这可能是相同的内容:dzone.com/articles/quick-tip-%E2%80%93-typescript-declare【参考方案5】:
找到了我要找的东西:
声明与 var
var
创建一个新变量。 declare
用于告诉 TypeScript 该变量已在别处创建。如果您使用declare
,则不会向生成的 JavaScript 添加任何内容 - 它只是对编译器的提示。
例如,如果您使用定义 var externalModule
的外部脚本,您将使用 declare var externalModule
向 TypeScript 编译器提示 externalModule
已设置
【讨论】:
我有一个类似的场景,外部 JS 定义了一个变量externalModule
等等。 externalModule
在运行时未定义但其他一些变量未定义的原因可能是什么?以上是关于“export declare class Actions”中的“declare”有啥作用?的主要内容,如果未能解决你的问题,请参考以下文章