Modul impor Type6 es6 “File bukan kesalahan modul”

127

Saya menggunakan naskah 1.6 dengan sintaks modul es6.

File saya adalah:

test.ts:

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

main.ts:

import App from './test';

var a = new App.SomeClass();

Ketika saya mencoba untuk mengkompilasi main.tsfile saya mendapatkan kesalahan ini:

Kesalahan TS2306: File 'test.ts' bukan modul.

Bagaimana saya bisa mencapai itu?

Bazinga
sumber
Saya memiliki masalah ini, saya tidak memiliki konstruktor di kelas, menambahkan satu dan masalah hilang
dorriz

Jawaban:

139

Extended - untuk memberikan rincian lebih lanjut berdasarkan beberapa komentar

Kesalahannya

Kesalahan TS2306: File 'test.ts' bukan modul.

Berasal dari fakta yang dijelaskan di sini http://exploringjs.com/es6/ch_modules.html

17. Modul

Bab ini menjelaskan cara kerja modul built-in di ECMAScript 6.

17.1 Ikhtisar

Dalam ECMAScript 6, modul disimpan dalam file. Hanya ada satu modul per file dan satu file per modul. Anda memiliki dua cara mengekspor barang dari modul. Dua cara ini bisa dicampur, tetapi biasanya lebih baik menggunakannya secara terpisah.

17.1.1 Beberapa ekspor bernama

Mungkin ada beberapa ekspor bernama:

//------ 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 Ekspor standar tunggal

Mungkin ada satu ekspor standar. Misalnya, suatu fungsi:

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

Berdasarkan hal di atas kita perlu export, sebagai bagian dari file test.js. Mari sesuaikan kontennya seperti ini:

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

Dan sekarang kita dapat mengimpornya dengan tiga cara berikut:

import * as app1 from "./test";
import app2 = require("./test");
import {App} from "./test";

Dan kita dapat mengkonsumsi barang impor seperti ini:

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

dan panggil metode untuk melihatnya beraksi:

console.log(a1.getName())
console.log(a2.getName())
console.log(b1.getName())
console.log(b2.getName())
console.log(c1.getName())
console.log(c2.getName())

Bagian asli berusaha membantu mengurangi jumlah kompleksitas dalam penggunaan namespace

Bagian asli:

Saya akan sangat menyarankan untuk memeriksa T & J ini:

Bagaimana cara menggunakan ruang nama dengan modul eksternal TypeScript?

Biarkan saya mengutip kalimat pertama:

Jangan gunakan "ruang nama" dalam modul eksternal.

Jangan lakukan ini.

Serius. Berhenti.

...

Dalam hal ini, kita tidak perlu modulemasuk test.ts. Ini bisa jadi konten yang disesuaikan test.ts:

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

Baca lebih lanjut di sini

Ekspor =

Pada contoh sebelumnya, ketika kami mengonsumsi setiap validator, setiap modul hanya mengekspor satu nilai. Dalam kasus seperti ini, sulit untuk bekerja dengan simbol-simbol ini melalui nama mereka yang memenuhi syarat ketika pengidentifikasi tunggal akan melakukan hal yang sama baiknya.

The export =sintaks menentukan satu objek yang diekspor dari modul . Ini bisa berupa kelas, antarmuka, modul, fungsi, atau enum. Saat diimpor, simbol yang diekspor dikonsumsi langsung dan tidak memenuhi syarat dengan nama apa pun.

nanti kita bisa mengkonsumsinya seperti ini:

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

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

sc.getName();

Baca lebih lanjut di sini:

Modul Pemuatan Opsional dan Skenario Pemuatan Lanjutan Lainnya

Dalam beberapa kasus, Anda mungkin hanya ingin memuat modul dalam beberapa kondisi. Dalam TypeScript, kita dapat menggunakan pola yang ditunjukkan di bawah ini untuk menerapkan ini dan skenario pemuatan lanjutan lainnya untuk secara langsung memanggil pemuat modul tanpa kehilangan keamanan jenis.

Kompiler mendeteksi apakah setiap modul digunakan dalam JavaScript yang dipancarkan. Untuk modul yang hanya digunakan sebagai bagian dari sistem tipe, tidak ada panggilan yang diperlukan yang dipancarkan. Pemusnahan referensi yang tidak digunakan ini adalah optimalisasi kinerja yang baik, dan juga memungkinkan pemuatan opsional modul-modul tersebut.

Gagasan inti dari pola adalah bahwa impor id = memerlukan ('...') pernyataan memberi kita akses ke jenis yang diekspos oleh modul eksternal. Pemuat modul dipanggil (melalui keharusan) secara dinamis, seperti yang ditunjukkan pada blok if di bawah ini. Ini memanfaatkan optimisasi pemusnahan referensi sehingga modul hanya dimuat saat dibutuhkan. Agar pola ini berfungsi, penting bahwa simbol yang ditentukan melalui impor hanya digunakan dalam posisi jenis (yaitu tidak pernah dalam posisi yang akan dipancarkan ke JavaScript).

Radim Köhler
sumber
1
Tapi ini: import App = require ('./ test'); bukan sintaks dari modul ES6. ini adalah js umum. Bisakah saya melakukannya dengan sintaks modul es6?
Bazinga
@ JsIsAwesome Anda sedang mencoba untuk mencampur modul JS dengan modul TypeScript. Anda harus menggunakan satu atau yang lain, bukan campuran keduanya.
JJJ
Jawaban ini tidak merujuk pada sintaks
ES6
@phiresky, apa maksudmu?
Radim Köhler
1
Terima kasih, itu hebat.
phiresky
24

Jawaban di atas benar. Tapi kalau-kalau ... Mendapat kesalahan yang sama dalam Kode VS. Harus menyimpan kembali / mengkompilasi ulang file yang sedang melempar kesalahan.

A. Tim
sumber
3
Ini berhasil untuk saya. Saya cukup menghapus titik koma, menambahkannya kembali dan menyimpan file itu lagi, dan kemudian menjalankan Webpack berhasil. Waktu yang tepat untuk hidup.
Ray Hogan
1
Saya sudah terbiasa dengan Webstorm dan tidak menyadari bahwa file tidak disimpan secara otomatis dalam Kode VS. Jawaban ini menyelamatkan saya dari banyak rasa sakit, terima kasih.
cib
Ada pengaturan untuk penyimpanan otomatis dalam Kode VS. Saya tidak menggunakannya karena VS Code sudah mencadangkan file yang belum disimpan dan saya tidak selalu menggunakan git.
aamarks
13

Bagaimana saya bisa mencapai itu?

Contoh Anda mendeklarasikan modul internal TypeScript <1.5 , yang sekarang disebut namespace . module App {}Sintaksis lama sekarang setara dengan namespace App {}. Akibatnya, berikut ini berfungsi:

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

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

Yang telah dibilang...

Cobalah untuk menghindari mengekspor ruang nama dan bukannya mengekspor modul (yang sebelumnya disebut modul eksternal ). Jika perlu, Anda dapat menggunakan namespace saat impor dengan pola impor namespace seperti ini:

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

// main.ts
import * as App from './test'; // namespace import pattern
var a = new App.SomeClass();
Shaun Luttin
sumber
1
Itu masih praktik yang bagus? Menurut jawaban ini ( stackoverflow.com/a/35706271/2021224 ), mencoba mengimpor fungsi atau kelas seperti ini lalu memintanya - "ilegal menurut spesifikasi ES6".
Andrey Prokhorov
2

Selain jawaban A. Tim ada kalanya bahkan itu tidak berhasil, jadi Anda perlu:

  1. Tulis ulang string impor, menggunakan intellisense. Terkadang ini memperbaiki masalah
  2. Mulai ulang VS Code
ZenVentzi
sumber
1
sama untuk stackblitz - file kompilasi yang mengimpor modul dan semua berfungsi dengan baik, tepuk tangan
godblessstrawberry
Saya juga mengalami ini ketika kode saya tidak diformat dengan benar. VSCode indentasi kode kelas copy + paste saya ketika saya membagi kelas saya ke dalam file mereka sendiri, dan VSCode membuat indentasi semuanya setelah export class... {, yang sudutnya tidak suka, memberi saya masalah ini. Setelah memperbaiki format, kompilasi tanpa masalah.
Guy Park
0

Selain jawaban Tim, masalah ini terjadi pada saya ketika saya sedang membagi file refactoring, membaginya menjadi file mereka sendiri.

VSCode, untuk beberapa alasan, menjorok bagian dari kode [class] saya, yang menyebabkan masalah ini. Ini sulit untuk diketahui pada awalnya, tetapi setelah saya menyadari kode itu indentasi, saya memformat kode dan masalah itu hilang.

misalnya, segala sesuatu setelah baris pertama definisi Kelas diindentasi secara otomatis selama menempel.

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

    constructor() { ... }
  }
Taman Guy
sumber