Typescript es6インポートモジュール「ファイルはモジュールエラーではありません」


127

私はes6モジュール構文でtypescript 1.6を使用しています。

私のファイルは:

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'はモジュールではありません。

どうすればそれを達成できますか?


私にはこの問題がありました。クラスにコンストラクターがありませんでした。1つ追加して問題は解消しました
dorriz

回答:


139

拡張 -一部のコメントに基づいて詳細を提供する

エラー

エラーTS2306:ファイル 'test.ts'はモジュールではありません。

ここで説明されている事実から来ていますhttp://exploringjs.com/es6/ch_modules.html

17.モジュール

この章では、組み込みモジュールがECMAScript 6でどのように機能するかについて説明します。

17.1概要

ECMAScript 6では、モジュールはファイルに保存されます。ファイルごとに1つのモジュールと、モジュールごとに1つのファイルがあります。モジュールから物事をエクスポートする方法は2つあります。これら2つの方法は混在させることができますが、通常は別々に使用する方が適切です。

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単一のデフォルトのエクスポート

デフォルトのエクスポートは1つです。たとえば、関数:

//------ myFunc.js ------
export default function () { ··· } // no semicolon!

上記に基づいて、test.jsファイルのexport一部としてが必要です。その内容を次のように調整してみましょう。

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

そして、次の3つの方法でインポートできます。

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())

元の部分は、名前空間の使用における複雑さの量を減らすのに役立つことを試みています

元のパーツ:

このQ&Aを確認することを強くお勧めします。

TypeScript外部モジュールで名前空間を使用するにはどうすればよいですか?

最初の文を引用しましょう:

外部モジュールで「名前空間」を使用しないでください。

これを行わないでください。

真剣に。やめる。

...

この場合、のmodule内部は必要ありませんtest.ts。これは調整されたその内容である可能性がありますtest.ts

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

詳細はこちら

エクスポート=

前の例では、各バリデーターを使用したときに、各モジュールは1つの値のみをエクスポートしました。このような場合、単一の識別子でも同様に機能するのに、修飾名を使用してこれらの記号を操作するのは面倒です。

export =構文は、指定のモジュールからエクスポートされた単一のオブジェクトを。これは、クラス、インターフェース、モジュール、関数、または列挙型です。インポートされると、エクスポートされたシンボルは直接消費され、名前で修飾されません。

後で次のように使用できます。

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

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

sc.getName();

詳細はこちら:

オプションのモジュールの読み込みとその他の高度な読み込みシナリオ

場合によっては、特定の条件下でのみモジュールをロードする必要があります。TypeScriptでは、以下に示すパターンを使用して、これと他の高度な読み込みシナリオを実装し、型の安全性を失うことなくモジュールローダーを直接呼び出すことができます。

コンパイラは、発行されたJavaScriptで各モジュールが使用されているかどうかを検出します。型システムの一部としてのみ使用されるモジュールの場合、require呼び出しは発行されません。この未使用の参照のカリングは、優れたパフォーマンス最適化であり、これらのモジュールのオプションのロードも可能にします。

このパターンの核となる考え方は、import id = require( '...')ステートメントにより、外部モジュールによって公開されている型へのアクセスを提供することです。以下のifブロックに示すように、モジュールローダーは(requireを介して)動的に呼び出されます。これにより、リファレンスカリングの最適化が活用され、必要な場合にのみモジュールがロードされます。このパターンが機能するためには、インポートを介して定義されたシンボルがタイプの位置でのみ使用されることが重要です(つまり、JavaScriptに出力される位置では決して使用されません)。


1
しかしこれ:import App = require( './ test'); es6モジュールの構文ではありません。これは一般的なjsです。es6モジュールの構文でそれを行うことはできますか?
Bazinga 2015

@JsIsAwesome JSモジュールとTypescriptモジュールを混在させようとしています。両方を混合するのではなく、どちらか一方を使用する必要があります。
JJJ 2015

この回答はES6の構文には言及していません
phiresky

@phiresky、どういう意味ですか?
RadimKöhler15年

1
ありがとうございます。
phiresky

24

上記の答えは正しいです。しかし念のために... VSコードで同じエラーが発生しました。エラーをスローしていたファイルを再保存/再コンパイルする必要がありました。


3
これでうまくいきました。セミコロンを削除して再度追加し、ファイルを再度保存するだけで、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仕様によると不正です」とのことです。
Andrey Prokhorov

2

A.ティムの答えに加えてに、それでもうまくいかない場合があるため、次のことを行う必要があります。

  1. インテリセンスを使用して、インポート文字列を書き換えます。時々これは問題を修正します
  2. VSコードを再起動

1
stackblitzでも同じ-モジュールをインポートしてすべて正常に機能する再コンパイルされたファイル、乾杯
godblessstrawberry '25

また、コードが正しくフォーマットされていない場合にもこの問題が発生しました。VSCodeは、クラスを独自のファイルに分割するときに、コピー+貼り付けクラスのコードをインデントしましたexport class... {。フォーマットを修正した後、問題なくコンパイルされました。
ガイ・パーク

0

Timの回答に加えて、この問題は、リファクタリングファイルを分割して、独自のファイルに分割したときに発生しました。

VSCodeが何らかの理由で[クラス]コードのインデントされたため、この問題が発生しました。これは最初は気づきませんでしたが、コードがインデントされていることに気付いた後、コードをフォーマットすると問題は解消しました。

たとえば、クラス定義の最初の行の後のすべては、貼り付け中に自動インデントされました。

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

    constructor() { ... }
  }
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.