TypeScript ES6 导入模块“文件不是模块错误”

新手上路,请多包涵

我正在使用带有 ES6 模块语法的 TypeScript 1.6。

我的文件是:

测试.ts:

 module App {
  export class SomeClass {
    getName(): string {
      return 'name';
    }
  }
}

main.ts:

 import App from './test';

var a = new App.SomeClass();

当我尝试编译 main.ts 文件时,我收到此错误:

错误 TS2306:文件“test.ts”不是模块。

我怎样才能做到这一点?

原文由 Bazinga 发布,翻译遵循 CC BY-SA 4.0 许可协议

阅读 4k
2 个回答

扩展- 根据一些评论提供更多细节

错误

错误 TS2306:文件“test.ts”不是模块。

来自这里描述的事实 http://exploringjs.com/es6/ch_modules.html

17. 模块

本章解释了内置模块在 ECMAScript 6 中是如何工作的。

17.1 概述

在 ECMAScript 6 中,模块存储在文件中。每个文件只有一个模块,每个模块一个文件。您有两种从模块中导出内容的方法。这两种方式可以混合使用,但通常最好分开使用。

17.1.1 多个命名导出

可以有多个命名导出:

>  //------ lib.js ------
> export const sqrt = Math.sqrt;
> export function square(x) {
>     return x * x;
> }
> export function diag(x, y) {
>     return sqrt(square(x) + square(y));
> }
> ...
>
> ```
>
> **17.1.2 单一默认导出**
>
> 可以有一个默认导出。例如,一个函数:
>
> ```
>  //------ myFunc.js ------
> export default function () { ··· } // no semicolon!
>
> ```

基于上述,我们需要 **`export`** 作为 **test.js** 文件的一部分。让我们像这样调整它的内容:

// test.js - exporting es6 export module App { export class SomeClass { getName(): string { return ‘name’; } } export class OtherClass { getName(): string { return ‘name’; } } }


现在我们可以通过以下三种方式导入它:

import * as app1 from “./test”; import app2 = require(“./test”); import {App} from “./test”;


我们可以像这样消费进口的东西:

var a1: app1.App.SomeClass = new app1.App.SomeClass(); var a2: app1.App.OtherClass = new app1.App.OtherClass();

var b1: app2.App.SomeClass = new app2.App.SomeClass(); var b2: app2.App.OtherClass = new app2.App.OtherClass();

var c1: App.SomeClass = new App.SomeClass(); var c2: App.OtherClass = new App.OtherClass();


并调用该方法以查看它的实际效果:

console.log(a1.getName()) console.log(a2.getName()) console.log(b1.getName()) console.log(b2.getName()) console.log(c1.getName()) console.log(c2.getName())


_原始部分试图帮助减少命名空间使用的复杂性_

### 原创部分:

我真的强烈建议检查这个问答:

## [如何将命名空间与 TypeScript 外部模块一起使用?](https://stackoverflow.com/q/30357634/1679310)

让我引用第一句话:

> ### 不要在外部模块中使用“命名空间”。
>
> ### 不要这样做。
>
> ### 严重地。停止。
>
> ...

在这种情况下,我们只是不需要 **`module`** 里面的 `test.ts` 。这可能是它调整的内容 **`test.ts`** :

export class SomeClass { getName(): string { return ‘name’; } }


在这里阅读更多

### [出口 =](http://www.typescriptlang.org/Handbook\#modules-export-)

> 在前面的示例中,当我们消费每个验证器时,每个模块只导出一个值。在这种情况下,通过它们的限定名称来处理这些符号是很麻烦的,而单个标识符也可以。
>
> `export =` 语法指定 **从模块导出的单个对象**。这可以是类、接口、模块、函数或枚举。导入时,直接使用导出的符号,并且没有任何名称限定。

我们以后可以像这样使用它:

import App = require(‘./test’);

var sc: App.SomeClass = new App.SomeClass();

sc.getName();

”`

在这里阅读更多:

可选模块加载和其他高级加载场景

在某些情况下,您可能只想在某些条件下加载模块。在 TypeScript 中,我们可以使用下面显示的模式来实现这个和其他高级加载场景,以直接调用模块加载器而不会失去类型安全。

编译器检测每个模块是否在发出的 JavaScript 中使用。对于仅用作类型系统一部分的模块,不会发出任何要求调用。这种对未使用引用的剔除是一种很好的性能优化,并且还允许可选地加载这些模块。

该模式的核心思想是 import id = require(‘…’) 语句让我们可以访问外部模块公开的类型。模块加载器是动态调用的(通过 require),如下面的 if 块所示。这利用了引用剔除优化,以便仅在需要时加载模块。要使这种模式起作用,重要的是通过 import 定义的符号仅用于类型位置(即永远不会出现在将被发送到 JavaScript 中的位置)。

原文由 Radim Köhler 发布,翻译遵循 CC BY-SA 4.0 许可协议

我在没有导出的模块中遇到了同样的问题。我只将它用于副作用。这就是 TypeScript 文档关于导入副作用模块的说法

虽然不推荐实践,但某些模块设置了一些可供其他模块使用的全局状态。这些模块可能没有任何导出,或者消费者对它们的任何导出都不感兴趣。要导入这些模块,请使用:

>  import "./my-module.js";
>
> ```

在这种情况下,您可以通过简单地导出一个空对象来修复“文件不是模块”错误:

// side-effects stuff

export default {};

”`

原文由 dodov 发布,翻译遵循 CC BY-SA 4.0 许可协议

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题