打字稿es6导入模块“文件不是模块错误”


127

我将打字稿1.6与es6模块语法一起使用。

我的文件是:

test.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'不是一个模块。

我该怎么做?


我遇到了这个问题,我在课堂上没有构造函数,添加了一个问题,问题就消失了
dorriz

Answers:


139

扩展 -根据一些评论提供更多详细信息

错误

错误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外部模块一起使用?

让我引用第一句话:

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

不要这样

说真的 停止。

...

在这种情况下,我们不需要的module内部test.ts。这可能是调整后的内容test.ts

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

在这里阅读更多

出口=

在前面的示例中,当我们使用每个验证器时,每个模块仅导出一个值。在这种情况下,当单个标识符也可以通过合格名称使用这些符号时就很麻烦。

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

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

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

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

sc.getName();

在这里阅读更多:

可选模块加载和其他高级加载方案

在某些情况下,您可能只想在某些情况下加载模块。在TypeScript中,我们可以使用以下所示的模式来实现此加载方案和其他高级加载方案,以直接调用模块加载程序而不会丢失类型安全性。

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

模式的核心思想是import id = require('...')语句使我们可以访问外部模块公开的类型。模块加载器是动态调用的(通过require),如下面的if块所示。这利用了参考剔除优化,因此仅在需要时才加载模块。为了使这种模式有效,重要的是,通过import定义的符号仅在类型位置中使用(即,永远不要在将要发射到JavaScript中的位置中使用)。


1
但这是:import App = require('./ test'); 不是es6模块的语法。这是常见的js。我可以使用es6模块语法吗?
巴青加2015年

@JsIsAwesome您正在尝试将JS模块与Typescript模块混合使用。您需要使用一个或另一个,而不是两者的混合。
JJJ

此答案不涉及ES6语法
phiresky 2015年

@phiresky,你是什么意思?
RadimKöhler2015年

1
谢谢,太好了。
phiresky

24

以上答案是正确的。但是以防万一...在VS Code中遇到了相同的错误。必须重新保存/重新编译抛出错误的文件。


2
这对我有用。我只是删除了一个分号,将其重新添加并再次保存了文件,然后运行Webpack就可以了。活着的好时机。
雷·霍根

1
我已经习惯了Webstorm,却没有意识到文件不会自动保存在VS Code中。谢谢,这个答案让我省了很多苦。
cib

VS Code中有一个自动保存的设置。我不使用它,因为VS Code已经备份了未保存的文件,而且我并不总是使用git。
aamarks

13

我该怎么做?

您的示例声明一个TypeScript <1.5 内部模块,该模块现在称为名称空间。现在,旧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();

话虽如此...

尝试避免导出名称空间,而是导出模块(以前称为外部模块)。如果需要,可以在名称空间导入模式中使用如下所示的名称空间

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

// main.ts
import * as App from './test'; // namespace import pattern
var a = new App.SomeClass();

1
还是一个好习惯?根据此答案(stackoverflow.com/a/35706271/2021224),尝试导入这样的函数或类然后调用它-“根据ES6规范,这是非法的”。
安德烈·普罗霍罗夫

2

除了A. Tim的答案外,有时甚至无法解决问题,因此您需要:

  1. 使用intellisense重写导入字符串。有时这可以解决问题
  2. 重新启动VS Code

1
对于stackblitz一样-导入模块的重新编译文件,一切正常,欢呼
godblessstrawberry

当我的代码格式不正确时,我也遇到了这种情况。当我将类拆分为自己的文件时,VSCode缩进我的复制粘贴类代码,而VSCode缩进了export class... {,之后的所有内容都缩进了,这是我不喜欢的,这给了我这个问题。修复格式后,编译没有问题。
Guy Park

0

除了蒂姆的答案,当我拆分一个重构文件,并将其拆分成自己的文件时,这个问题对我也发生了。

出于某种原因,VSCode缩进了[class]代码的一部分,从而导致了此问题。起初很难注意到,但是当我意识到代码缩进之后,我格式化了代码,问题就消失了。

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

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

    constructor() { ... }
  }
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.