Javascript Typescript es6 导入模块“文件不是模块错误”
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/32805559/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Typescript es6 import module "File is not a module error"
提问by Bazinga
I am using typescript 1.6 with es6 modules syntax.
我正在使用带有 es6 模块语法的 typescript 1.6。
My files are:
我的文件是:
test.ts:
测试.ts:
module App {
export class SomeClass {
getName(): string {
return 'name';
}
}
}
main.ts:
main.ts:
import App from './test';
var a = new App.SomeClass();
When I am trying to compile the main.ts
file I get this error:
当我尝试编译main.ts
文件时,出现此错误:
Error TS2306: File 'test.ts' is not a module.
错误 TS2306:文件“test.ts”不是模块。
How can I accomplish that?
我怎样才能做到这一点?
回答by Radim K?hler
Extended- to provide more details based on some comments
扩展- 根据一些评论提供更多细节
The error
错误
Error TS2306: File 'test.ts' is not a module.
错误 TS2306:文件“test.ts”不是模块。
Comes from the fact described here http://exploringjs.com/es6/ch_modules.html
来自这里描述的事实http://exploringjs.com/es6/ch_modules.html
17. Modules
This chapter explains how the built-in modules work in ECMAScript 6.
17.1 OverviewIn ECMAScript 6, modules are stored in files. There is exactly one module per file and one file per module. You have two ways of exporting things from a module. These two ways can be mixed, but it is usually better to use them separately.
17.1.1 Multiple named exports
There can be multiple named exports:
//------ 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 Single default export
There can be a single default export. For example, a function:
//------ myFunc.js ------ export default function () { ··· } // no semicolon!
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!
Based on the above we need the export
, as a part of the test.jsfile. Let's adjust the content of it like this:
基于上述,我们需要export
, 作为test.js文件的一部分。让我们像这样调整它的内容:
// test.js - exporting es6
export module App {
export class SomeClass {
getName(): string {
return 'name';
}
}
export class OtherClass {
getName(): string {
return 'name';
}
}
}
And now we can import it with these thre ways:
现在我们可以通过以下三种方式导入它:
import * as app1 from "./test";
import app2 = require("./test");
import {App} from "./test";
And we can consume imported stuff like this:
我们可以像这样消费进口的东西:
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();
and call the method to see it in action:
并调用该方法以查看它的运行情况:
console.log(a1.getName())
console.log(a2.getName())
console.log(b1.getName())
console.log(b2.getName())
console.log(c1.getName())
console.log(c2.getName())
Original part is trying to help to reduce the amount of complexity in usage of the namespace
原始部分试图帮助减少名称空间使用的复杂性
Original part:
原始部分:
I would really strongly suggest to check this Q & A:
我真的强烈建议检查这个问答:
How do I use namespaces with TypeScript external modules?
如何将命名空间与 TypeScript 外部模块一起使用?
Let me cite the first sentence:
让我引用第一句话:
Do not use "namespaces" in external modules.
Don't do this.
Seriously. Stop.
...
不要在外部模块中使用“命名空间”。
不要这样做。
严重地。停止。
...
In this case, we just do not need module
inside of test.ts
. This could be the content of it adjusted test.ts
:
在这种情况下,我们只是不需要module
在test.ts
. 这可能是它调整的内容test.ts
:
export class SomeClass
{
getName(): string
{
return 'name';
}
}
Read more here
在这里阅读更多
Export =
出口 =
In the previous example, when we consumed each validator, each module only exported one value. In cases like this, it's cumbersome to work with these symbols through their qualified name when a single identifier would do just as well.
The
export =
syntax specifies a single object that is exported from the module. This can be a class, interface, module, function, or enum. When imported, the exported symbol is consumed directly and is not qualified by any name.
在前面的示例中,当我们使用每个验证器时,每个模块仅导出一个值。在这种情况下,通过它们的限定名称处理这些符号是很麻烦的,而单个标识符也可以这样做。
的
export =
语法指定该从模块中导出的单个对象。这可以是类、接口、模块、函数或枚举。导入时,导出的符号被直接使用,没有任何名称限定。
we can later consume it like this:
我们稍后可以像这样使用它:
import App = require('./test');
var sc: App.SomeClass = new App.SomeClass();
sc.getName();
Read more here:
在此处阅读更多信息:
Optional Module Loading and Other Advanced Loading Scenarios
可选模块加载和其他高级加载场景
In some cases, you may want to only load a module under some conditions. In TypeScript, we can use the pattern shown below to implement this and other advanced loading scenarios to directly invoke the module loaders without losing type safety.
The compiler detects whether each module is used in the emitted JavaScript. For modules that are only used as part of the type system, no require calls are emitted. This culling of unused references is a good performance optimization, and also allows for optional loading of those modules.
The core idea of the pattern is that the import id = require('...') statement gives us access to the types exposed by the external module. The module loader is invoked (through require) dynamically, as shown in the if blocks below. This leverages the reference-culling optimization so that the module is only loaded when needed. For this pattern to work, it's important that the symbol defined via import is only used in type positions (i.e. never in a position that would be emitted into the JavaScript).
在某些情况下,您可能只想在某些条件下加载模块。在 TypeScript 中,我们可以使用下面显示的模式来实现这个和其他高级加载场景,以直接调用模块加载器而不会失去类型安全性。
编译器检测每个模块是否在发出的 JavaScript 中使用。对于仅用作类型系统一部分的模块,不会发出 require 调用。剔除未使用的引用是一种很好的性能优化,并且还允许选择性加载这些模块。
该模式的核心思想是 import id = require('...') 语句让我们可以访问外部模块公开的类型。模块加载器是动态调用的(通过 require),如下面的 if 块所示。这利用了引用剔除优化,以便仅在需要时加载模块。为了让这个模式起作用,重要的是通过 import 定义的符号仅用于类型位置(即永远不会在将被发送到 JavaScript 的位置中)。
回答by A. Tim
Above answers are correct. But just in case... Got same error in VS Code. Had to re-save/recompile file that was throwing error.
以上答案都是正确的。但以防万一……在 VS Code 中遇到同样的错误。不得不重新保存/重新编译抛出错误的文件。
回答by Shaun Luttin
How can I accomplish that?
我怎样才能做到这一点?
Your example declares a TypeScript < 1.5 internal module, which is now called a namespace. The old module App {}
syntax is now equivalent to namespace App {}
. As a result, the following works:
您的示例声明了一个 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();
That being said...
话虽如此...
Try to avoid exporting namespacesand instead export modules (which were previously called external modules). If needs be you can use a namespace on import with the namespace import patternlike this:
尽量避免导出命名空间,而是导出模块(以前称为外部模块)。如果需要,您可以在导入时使用命名空间和命名空间导入模式,如下所示:
// test.ts
export class SomeClass {
getName(): string {
return 'name';
}
}
// main.ts
import * as App from './test'; // namespace import pattern
var a = new App.SomeClass();
回答by ZenVentzi
In addition to A. Tim's answerthere are times when even that doesn't work, so you need to:
除了A. Tim 的回答之外,有时即使这样也行不通,因此您需要:
- Rewrite the import string, using the intellisense. Sometimes this fixes the issue
- Restart VS Code
- 使用智能感知重写导入字符串。有时这可以解决问题
- 重新启动 VS 代码
回答by Guy Park
In addition to Tim's answer, this issue occurred for me when I was splitting up a refactoring a file, splitting it up into their own files.
除了蒂姆的回答之外,当我拆分重构文件,将其拆分为自己的文件时,我也遇到了这个问题。
VSCode, for some reason, indented parts of my [class] code, which caused this issue. This was hard to notice at first, but after I realised the code was indented, I formatted the code and the issue disappeared.
由于某种原因,VSCode 缩进了我的 [class] 代码的一部分,这导致了这个问题。起初很难注意到这一点,但在我意识到代码缩进后,我格式化了代码,问题就消失了。
for example, everything after the first line of the Class definition was auto-indented during the paste.
例如,在粘贴过程中,类定义的第一行之后的所有内容都会自动缩进。
export class MyClass extends Something<string> {
public blah: string = null;
constructor() { ... }
}