Kesalahan TypeScript TS2449: Kelas 'x' digunakan sebelum deklarasinya
Saya tidak memahami proses kompilasi tsc terkait dengan <reference> dan pembagian kelas dari sebuah namespace ke beberapa file. Saya menggunakan pola:
src/base.ts
namespace MyNameSpace {
export class Base {
/** constructor, etc. */
}
}
src/subclass.ts
/// <reference path="./base.ts" />
namespace MyNameSpace {
export class Subclass {
/** constructor, etc. */
}
}
Contoh sepele ini berhasil. Tapi saat saya menggunakan pola ini pada lebih banyak file, saya secara berkala mendapatkan error TypeScript error TS2449: Class 'x' digunakan sebelum deklarasinya..
Apakah kita kembali ke mengelola urutan deklarasi secara manual, seperti file .c/.h? Jika ya, alat apa yang akan membantu melacak referensi untuk menemukan kesalahan?
Tujuan saya adalah memiliki sekumpulan file yang dapat dikelola dan dikompilasi menjadi satu .js dan .d.ts (untuk digunakan oleh library TypeScript lain). Apakah ada solusi yang lebih baik untuk skenario ini? Upaya dengan variasi Webpack dan import telah gagal bagi saya.
Jika penting, saya juga menggunakan namespace bersarang, di mana anggotanya didefinisikan dalam subdirektori. Saya selalu menggunakan jalur referensi relatif.
Ini sangat mirip dengan TypeScript Tipe dasar 'xxxx' dirujuk sebelum deklarasinya, yang berkaitan dengan modul yang dibagi di beberapa file.
Jawaban #1
Peringatan Terminologi Utama
Namespace tidak lebih diutamakan daripada modul. Ini adalah poin yang sangat penting. Mari kita menyelami sejarahnya...
Namespace dahulu dideklarasikan seperti ini:
module MyNamespace {
}
Tapi sekarang mereka dideklarasikan seperti ini:
namespace MyNamespace {
}
Saat mendeklarasikan sebuah namespace, kata kunci namespace lebih disukai daripada kata kunci lama module.
Alasan kata kunci module diganti dengan namespace adalah karena orang sering bingung dengan "module". Anda bisa melihat dari mana kebingungan itu muncul! Sekarang module yang sebenarnya (yaitu file yang mengekspor atau mengimpor sesuatu) sebenarnya sedikit lebih baik daripada namespace, itulah sebabnya saya telah menghabiskan seluruh jawaban sejauh ini untuk membahas semua ini.
Gunakan Modul
Dengan ini dalam pikiran, Anda mungkin ingin mempertimbangkan penggunaan modul. Setiap modul memberi Anda konteks penamaan dan menjaga agar hal-hal tidak masuk ke dalam ruang lingkup global. Anda dapat mengimpor dan mengekspor dan semuanya seharusnya bekerja seperti yang diharapkan (dan Anda masih bisa menggabungkannya jika mau).
src/base.ts
export class Base {
}
src/subclass.ts
import * as Example from './subclass.ts';
export class Base extends Example.Base {
}
Penggabungan Namespace
Jika Anda ingin tetap menggunakan namespace, Anda harus menghormati bahwa semua yang Anda tempatkan di dalam sebuah namespace (bahkan ketika namespace itu tersebar di beberapa file) berkontribusi pada satu konteks penamaan... jadi Anda harus memberi nama subclass dengan berbeda.
src/base.ts
namespace MyNameSpace {
export class Base {
/** constructor, etc. */
}
}
src/subclass.ts
/// <reference path="./base.ts" />
namespace MyNameSpace {
export class Sub extends Base {
/** constructor, etc. */
}
}
Jadi pada akhirnya, Anda dapat memilih modul (modul eksternal yang tepat) di mana setiap file memiliki konteks penamaan sendiri, dan Anda dapat dengan mudah menghindari bentrokan penamaan - atau namespace di mana Anda perlu menyadari bahwa setiap namespace adalah satu konteks penamaan.
Cetakan Kecil
Dalam banyak contoh, saya telah mewarisi Base di subclass untuk ilustrasi. Pertanyaan Anda tidak persis seperti itu, tetapi saya ingin mengilustrasikan konsepnya. Pertanyaannya memiliki dua kelas dalam namespace yang sama dengan nama yang sama, yang merupakan konflik nama duplikat.
Jawaban #2
Saya berhasil menyelesaikan kesalahan ini dengan memulai ulang Visual Studio seperti yang disebutkan di komentar oleh @Quentin2
