gpt4 book ai didi

javascript - TypeScript模块导入和WebPack

转载 作者:搜寻专家 更新时间:2023-10-30 21:30:30 25 4
gpt4 key购买 nike

我在让WebPack为用TypeScript编写的项目注入(inject)导入的依赖项时遇到麻烦。我的第一个问题是让TypeScript识别导入的模块。

我有一个 header.ts 文件,该文件声明嵌套在vi.input下的模块并导出VIInputDirective类。在 main.ts 文件中,我尝试从 header.ts 文件导入导出的VIInputDirective类,但似乎无法让TypeScript识别它。

header.ts

module vi.input.header {
import IDirective = angular.IDirective;

export class VIInputDirective implements IDirective {
...
}
}

main.ts
import {VIInputDirective} from "./header.ts"; // Nothing imported; Cannot Resolve issue
VIInputDirective.whatever(); // Does not work

material.dt.s
declare module vi.input {
...
}

如果我将 main.ts 文件中的 import {VIInputDirective} from "./header.ts";交换为 import VIMHeaderDirective = vi.input.header.VIInputDirective;,则可以正常工作,但是在转译/注入(inject)时使用webpack会出现以下错误:
VM1469:1Uncaught ReferenceError: vi is not defined

我试过直接导出vi.input.header模块(即导出模块vi.input.header),但是没有用。我还尝试使用引用sytnax来包含文件,但这也不起作用: ///<reference path="file_path"/>

这是模块嵌套的问题,因为如果我删除模块并直接导出VIInputDirective类,则可以正常工作。但是,我想将其保留在嵌套模块中。

最佳答案

您没有使用模块。模块具有一个或多个顶级importexport语句。而是使用全局 namespace 并创建全局 namespace 的子 namespace 来组织程序。这称为显示模块模式。它不涉及使用模块。
不幸的是,TypeScript曾经将此模式称为使用内部模块。此后,该术语已被弃用,强烈建议不要使用module x {}语法(请注意"周围缺少x)。
该语言引入了同义词namespace,以减少困惑。
Webpack,RequireJS和SystemJS之类的JavaScript加载程序和 bundle 程序可与模块一起使用,这就是TypeScript所称的外部模块。
为了澄清您提到的以下构造,模块无关

  • 顶层,未导出的module / namespace语法声明
    module vi.input.header { ... }
    现在写成
    namespace vi.input.header { ... }
    为了最大程度地减少困惑,但无论如何,总是会产生辐射。
    var vi;
    (function (vi) {
    var input;
    (function (input) {
    var header;
    (function (header) {
    })(header = input.header || (input.header = {}));
    })(input = vi.input || (vi.input = {}));
    })(vi || (vi = {}));
    请注意,这会以各种库常用的模式更改全局范围。类似于上面的namespace s(以前称为内部模块)具有有趣的属性,即多个文件可以贡献其内容,这实际上是其主要目的。这就解释了嵌套的程度以及上面的输出中对变量的条件赋值。这与使用模块无关。
  • 引用 import成员的
  • namespace分配,例如
    import IDirective = angular.IDirective;
    不属于顶级import声明,因此不会导致其包含文件被视为模块。即使将它们放在文件的顶层也是如此。原因是模块系统(无论是AMD,CommonJS,System还是ES2015),所有都使用字符串作为模块说明符,并从此类字符串中导入。可能代表文件路径,URL,解析的简单名称或合成模块ID。

  • 同样,代码中的 import name = qualified.global.name语句是TypeScript特定功能,与 模块无关。它们对于嵌套类型和值的别名很有用,但是它们却不能创建模块。
    现在,它变得有趣起来,并且与您的特定问题相交了。 namespace可以使用,并且有时很优雅地与外部模块中的 一起使用,但它们的语义却大不相同
    考虑
    services.ts
    export namespace app {
    export class SomeService { }
    }
    编译成以下JavaScript
    export var app;
    (function (app) {
    class SomeService {
    }
    app.SomeService = SomeService;
    })(app || (app = {}));
    main.ts
    export namespace app {
    export function bootstrap() { }
    }
    编译成以下JavaScript
    export var app;
    (function (app) {
    function bootstrap() { }
    app.bootstrap = bootstrap;
    })(app || (app = {}));
    上面的两个都是外部模块,也就是真正的模块,它们使用 namespace 作为内部代码组织机制,但是它们的主要要点是,它们 不为共享的app命名空间提供,它们各自具有自己的文件范围的 app变量。双方都没有对另一方成员的隐式访问, namespace app的声明不跨文件合并,并且它们具有相似的内部命名方案与它们的模块化无关。
    那么,所有这些与您的问题以及您尝试应用的建议有何关系?
    让我们来看看
    headers.ts
    module vi.input.header {
    import IDirective = angular.IDirective;

    export class VIInputDirective implements IDirective {
    static whatever() { }
    }
    }
    如上所述,该文件不是模块,而是使用全局 namespace 公开其声明。如果我们今天写这篇文章,按照惯例,我们将使用 namespace关键字而不是 module关键字。
    main.ts
    import {VIInputDirective} from "./header.ts"; // Nothing imported; Cannot Resolve issue
    VIInputDirective.whatever(); // Does not work
    实际上,这两行都行不通,因为您正在将 headers.ts 当作模块来导入,但是正如我们刚刚看到的,它不是模块。此外,第一行是从模块说明符字符串导入的顶级 import语句,具有讽刺意味的是,它使 main.ts 本身就是一个模块。
    简而言之,这两种样式不能很好地融合在一起,并且在它们之间共享代码并不简单,也不是您应该尝试做的事情(我将UMD格式保留在此答案之外,以使其保持相对简单)。
    现在我们来一圈
    强文本
    declare module vi.input {
    ....
    }

    If I swap import {VIInputDirective} from "./header.ts"; in the main.ts file with import VIMHeaderDirective = vi.input.header.VIInputDirective; it works fine, but then webpack on transpile/inject gives me the following error:


    确实如上所述。此 import的目标不是模块说明符字符串,并且不存在其他任何顶级导入或导出操作,它会更改 main.ts ,使其不再是模块。这将导致TypeScript对其进行TypeCheck正确检查,使用 import = namespace.value相互引用的全局变量是完全合法的,但是它们不是模块,而JavaScript工具(例如Webpack)则在模块上运行。
    那么,您将如何在这个勇敢的新世界中编写此应用程序?
    由于您使用的是Webpack模块 bundle 工具,因此您将一直使用适当的模块来编写它。
    main.ts
    import {VIInputDirective} from "./header.ts";
    VIInputDirective.whatever();
    headers.ts
    import {IDirective} from 'angular';

    export class VIInputDirective implements IDirective {
    static whatever() { }
    }
    不再像您编写本文时的样子,因为它已更新为可以使用适当的模块。如果您需要引用其中的内容,请使用模块语法
    my-dialog-options.ts
    import {material} from 'angular';

    const dialogOptions: material.IDialogOptions = { ... };

    export default dialogOptions;
    我尝试过分简化,但为避免就该主题写中篇小说,有必要挥手致意,但我相信我希望能涵盖并传达要点。

    关于javascript - TypeScript模块导入和WebPack,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39758237/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com