Typescript es6 导入module“文件不是module错误”

IT技术 javascript typescript ecmascript-6
2021-03-22 13:09:18

我正在使用带有 es6 module语法的 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”不是module。

我怎样才能做到这一点?

6个回答

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

错误

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

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

17. module

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

17.1 概述

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

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 外部module一起使用?

让我引用第一句话:

不要在外部module中使用“命名空间”。

不要这样做。

严重地。停止。

...

在这种情况下,我们只是不需要moduletest.ts. 这可能是它的内容调整test.ts

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

在这里阅读更多

出口 =

在前面的示例中,当我们使用每个验证器时,每个module仅导出一个值。在这种情况下,通过它们的限定名称使用这些符号是很麻烦的,而单个标识符也可以这样做。

export =语法指定该从module中导出的单个对象这可以是类、接口、module、函数或枚举。导入时,导出的符号被直接使用,没有任何名称限定。

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

import App = require('./test');

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

sc.getName();

在此处阅读更多信息:

可选module加载和其他高级加载场景

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

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

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

@phiresky,你是什么意思?
2021-04-23 13:09:18
@JsIsAwesome 您正在尝试将 JS module与 Typescript module混合使用。您需要使用一种或另一种,而不是两者的混合。
2021-04-24 13:09:18
示例使用import x = require('test')而 ES6 module语法看起来像import x from "test"
2021-04-30 13:09:18
但是这个: import App = require('./test'); 不是 es6 module的语法。这是常见的js。我可以用 es6 module语法来做吗?
2021-05-10 13:09:18
这个答案不涉及 ES6 语法
2021-05-14 13:09:18

以上答案都是正确的。但以防万一……在 VS Code 中遇到同样的错误。不得不重新保存/重新编译抛出错误的文件。

惊人的!我关闭文件并再次打开它,问题解决了,我猜这与在打开文件时更改文件名有关。
2021-04-23 13:09:18
这对我有用。我只是删除了一个分号,重新添加它并再次保存文件,然后运行 ​​Webpack 就可以了。活着的好时光。
2021-05-05 13:09:18
VS Code 中有一个自动保存设置。我不使用它,因为 VS Code 已经备份了未保存的文件,而且我并不总是使用 git。
2021-05-17 13:09:18
我习惯了 Webstorm 并且没有意识到文件不会自动保存在 VS Code 中。这个答案让我省去了很多痛苦,谢谢。
2021-05-18 13:09:18

我怎样才能做到这一点?

您的示例声明了一个 TypeScript < 1.5内部module,现在称为命名空间module App {}语法现在等效于namespace App {}. 结果,以下工作:

// test.ts
export namespace App {
    export class SomeClass {
        getName(): string {
            return 'name';
        }
    }
}

// main.ts
import { App } from './test';
var a = new App.SomeClass();

话虽如此...

尽量避免导出命名空间,而是导出module(以前称为外部module)。如果需要,您可以在导入时使用命名空间和命名空间导入模式,如下所示:

// test.ts
export class SomeClass {
    getName(): string {
        return 'name';
    }
}

// main.ts
import * as App from './test'; // namespace import pattern
var a = new App.SomeClass();
这仍然是一个好习惯吗?根据这个答案(stackoverflow.com/a/35706271/2021224),尝试导入这样的函数或类然后调用它 - “根据 ES6 规范是非法的”。
2021-04-28 13:09:18

除了A. Tim 的回答之外,有时即使这样也行不通,因此您需要:

  1. 使用智能感知重写导入字符串。有时这可以解决问题
  2. 重新启动 VS 代码
当我的代码格式不正确时,我也遇到过这种情况。当我将类拆分为自己的文件时,VSCode 缩进了我的复制粘贴类代码,而 VSCode 缩进了 . 之后的所有内容export class... {,角度不喜欢,这给了我这个问题。修复格式后,编译没有问题。
2021-04-23 13:09:18
与 stackblitz 相同 - 重新编译的文件导入module并且一切正常,干杯
2021-05-11 13:09:18

除了蒂姆的回答之外,当我拆分重构文件,将其拆分为自己的文件时,我也遇到了这个问题。

由于某种原因,VSCode 缩进了我的 [class] 代码的一部分,这导致了这个问题。起初很难注意到这一点,但在我意识到代码缩进后,我格式化了代码,问题就消失了。

例如,在 Class 定义的第一行之后的所有内容在粘贴过程中都会自动缩进。

export class MyClass extends Something<string> {
    public blah: string = null;

    constructor() { ... }
  }