【问题标题】: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 {
    ...
}

【问题讨论】:

标签: 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';),我不知道这是否是好的做法,但我觉得它很整洁! ^^

    请务必记住,向文件添加 importexport 会将其提升为模块,因此 declare 范围将不再处于全局级别。

    PS,有一个错误(issue 16671):如果您在声明中使用const enum(我为redux 操作类型这样做)并且您指定了transpileOnly 标志(create-react- app-typescript 包确实如此,这就是我知道的原因),枚举不会被内联!你可以跑进去,也可以不跑,但提前知道很有用!

    【讨论】:

    【解决方案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 文件。

    【讨论】:

    【解决方案5】:

    找到了我要找的东西:

    声明与 var

    var 创建一个新变量。 declare 用于告诉 TypeScript 该变量已在别处创建。如果您使用declare,则不会向生成的 JavaScript 添加任何内容 - 它只是对编译器的提示。

    例如,如果您使用定义 var externalModule 的外部脚本,您将使用 declare var externalModule 向 TypeScript 编译器提示 externalModule 已设置

    【讨论】:

    • 我有一个类似的场景,外部 JS 定义了一个变量 externalModule 等等。 externalModule 在运行时未定义但其他一些变量未定义的原因可能是什么?
    猜你喜欢
    • 2017-06-15
    • 2013-11-13
    • 2013-11-05
    • 1970-01-01
    • 2017-06-04
    • 1970-01-01
    • 2021-03-19
    • 1970-01-01
    • 2019-01-26
    相关资源
    最近更新 更多