Typescript es6导入模块“File is not a module error” [英] Typescript es6 import module "File is not a module error"

查看:8093
本文介绍了Typescript es6导入模块“File is not a module error”的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述



我的文件是:



test.ts:

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

main.ts :

 从'./test'导入应用程序; 

var a = new App.SomeClass();

当我尝试编译 main.ts 文件我得到这个错误:


错误TS2306:文件'test.ts'不是一个模块。 >


如何实现?

解决方案<



错误


错误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;
导出函数square(x){
return x * x;
}
导出函数diag(x,y){
return sqrt(square(x)+ square(y));
}
...

17.1.2单个默认导出



可以有一个默认导出。例如,一个函数:

  // ------ myFunc.js ------ 
export default function(){...} //没分号!


根据上述,我们需要 export ,作为 test.js 文件的一部分。让我们调整它的内容:

  // test.js  - 导出es6 
导出模块App {
export class SomeClass {
getName():string {
return'name';
}
}
export class OtherClass {
getName():string {
return'name';
}
}
}

现在我们可以导入有以下几种方式:

  import *作为app1从./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())

原始部分正试图帮助减少使用命名空间的复杂程度



原始部分:



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



如何在TypeScript外部模块中使用命名空间?



让我引用第一句话:


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



不要这样做。



严重。停止。



...


在这种情况下,我们只是做 test.ts 中不需要 模块 。这可能是其内容调整了 test.ts

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

在这里阅读更多



导出=




在上一个例子中,当我们消耗每个验证器时,每个模块只导出一个值。在这种情况下,当单个标识符也可以同时使用这些符号时,使用这些符号是很麻烦的。



export = 语法指定从模块导出的单个对象。这可以是一个类,接口,模块,函数或枚举。导入时,导出的符号直接消耗,不被任何名称限定。


我们以后可以这样消费: p>

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

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

sc.getName();

在此阅读更多:



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




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



编译器检测每个模块用于发布的JavaScript。对于仅用作类型系统的一部分的模块,不需要调用。未使用的引用的这种剔除是一个很好的性能优化,也允许可选加载这些模块。



模式的核心思想是导入id = '...')语句让我们可以访问外部模块暴露的类型。动态调用模块加载程序(通过require),如下面的if块所示。这可以利用参考剔除优化,以便仅在需要时加载模块。为了使此模式正常工作,重要的是通过导入定义的符号仅用于类型位置(即从不处于将被发布到JavaScript中的位置)。



I am using typescript 1.6 with es6 modules syntax.

My files are:

test.ts:

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

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:

Error TS2306: File 'test.ts' is not a module.

How can I accomplish that?

解决方案

Extended - to provide more details based on some comments

The error

Error TS2306: File 'test.ts' is not a module.

Comes from the fact described here http://exploringjs.com/es6/ch_modules.html

17. Modules

This chapter explains how the built-in modules work in ECMAScript 6.

17.1 Overview

In 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!

Based on the above we need the export, as a part of the test.js file. Let's adjust the content of it like this:

// 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?

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:

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.

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 es6导入模块“File is not a module error”的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆