ข้อผิดพลาด TypeScript TS2449: คลาส 'x' ถูกใช้ก่อนที่จะมีการประกาศ
ฉันไม่เข้าใจกระบวนการคอมไพล์ tsc เกี่ยวกับ <reference> และการแยกคลาสของเนมสเปซออกเป็นหลายไฟล์ ฉันกำลังใช้รูปแบบดังนี้:
src/base.ts
namespace MyNameSpace {
export class Base {
/** constructor, etc. */
}
}
<รหัส>src/subclass.ts
/// <reference path="./base.ts" />
namespace MyNameSpace {
export class Subclass {
/** constructor, etc. */
}
}
ตัวอย่างง่าย ๆ นี้ใช้ได้ แต่เมื่อฉันใช้รูปแบบนี้กับไฟล์มากขึ้น ฉันจะได้ข้อผิดพลาดเป็นระยะ ๆ TypeScript error TS2449: Class 'x' ใช้ก่อนการประกาศ.
เรากลับไปจัดการลำดับการประกาศด้วยตนเองเหมือนกับไฟล์ .c/.h
เป้าหมายของฉันคือมีชุดไฟล์ที่จัดการได้ซึ่งคอมไพล์ออกมาเป็นไฟล์ .js และ .d.ts เพียงไฟล์เดียว (สำหรับใช้กับไลบรารี TypeScript อื่น) มีวิธีแก้ปัญหาที่ดีกว่าสำหรับสถานการณ์นี้ไหม? การลองใช้ Webpack และ import ในรูปแบบต่างๆ ล้มเหลวสำหรับฉัน
ถ้ามันสำคัญ ฉันก็ใช้เนมสเปซแบบซ้อนด้วย โดยที่สมาชิกถูกกำหนดในโฟลเดอร์ย่อย ฉันมักจะใช้เส้นทาง reference แบบสัมพันธ์เสมอ
นี่ค่อนข้างคล้ายกับ TypeScript ประเภทพื้นฐาน 'xxxx' ถูกอ้างอิงก่อนการประกาศ ซึ่งเกี่ยวข้องกับโมดูลที่แบ่งออกเป็นหลายไฟล์
คำตอบ #1
การแจ้งเตือนคำศัพท์สำคัญ
Namespace ไม่ได้ถูกชื่นชอบมากกว่าโมดูล นี่เป็นประเด็นที่สำคัญมาก มาลงลึกในประวัติกัน...
Namespace ถูกประกาศแบบนี้ในอดีต:
module MyNamespace {
}
แต่ตอนนี้พวกมันถูกประกาศแบบนี้:
namespace MyNamespace {
}
เมื่อประกาศ namespace จะใช้คำสำคัญ namespace แทนคำสำคัญ module เก่า
เหตุผลที่คำสำคัญ module ถูกแทนที่ด้วย namespace คือผู้คนสับสนกับ "โมดูล" คุณสามารถเห็นได้ว่าความสับสนอาจเกิดขึ้นจากตรงไหน! ตอนนี้ โมดูล จริงๆ (เช่น ไฟล์ที่ส่งออกหรือส่งเข้าบางอย่าง) จริงๆ แล้วดีกว่า namespace เล็กน้อย ซึ่งเป็นเหตุผลที่ฉันได้ใช้เวลาทั้งหมดในการตอบคำถามจนถึงตอนนี้เพื่ออธิบายทั้งหมดนี้
ใช้โมดูล
ด้วยสิ่งนี้ในใจ คุณอาจพิจารณาใช้โมดูล แต่ละโมดูลให้บริบทการตั้งชื่อแก่คุณและเก็บสิ่งต่าง ๆ ออกจากสโคปทั่วโลก คุณสามารถนำเข้าและส่งออก และทุกอย่างควรทำงานตามที่คาดไว้ (และคุณยังสามารถรวมมันถ้าคุณต้องการ)
src/base.ts
export class Base {
}
src/subclass.ts
import * as Example from './subclass.ts';
export class Base extends Example.Base {
}
การรวมเนมสเปซ
ถ้าคุณต้องการใช้งานกับ namespace คุณต้องเคารพว่าทุกสิ่งที่คุณใส่ภายใน namespace (แม้ว่า namespace นั้นจะแบ่งออกเป็นหลายไฟล์) จะมีส่วนช่วยในบริบทของการตั้งชื่อเพียงบริบทเดียว… ดังนั้นคุณจะต้องตั้งชื่อ subclass ให้แตกต่างกัน
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. */
}
}
ดังนั้นในที่สุด คุณสามารถเลือกโมดูล (โมดูลภายนอกที่ถูกต้อง) ซึ่งแต่ละไฟล์จะมีบริบทของการตั้งชื่อของตัวเอง และคุณสามารถหลีกเลี่ยงความชนกันของชื่อได้ง่าย หรือเลือกใช้เนมสเปซซึ่งคุณจะต้องตระหนักว่าแต่ละเนมสเปซเป็นบริบทการตั้งชื่อเดียว
ตัวอักษรเล็ก
ในหลายตัวอย่างฉันสืบทอด Base ในซับคลาสเพื่อการอธิบาย คุณถามไม่ได้ทำแบบนั้นเป๊ะ ๆ แต่ฉันต้องการอธิบายแนวคิด คำถามมีสองคลาสภายในเนมสเปซที่มีชื่อเดียวกัน ซึ่งเป็นความขัดแย้งจากชื่อซ้ำ
คำตอบ #2
ฉันสามารถแก้ไขข้อผิดพลาดนี้ได้โดยการ เริ่มต้น Visual Studio ใหม่ ตามที่ได้กล่าวไว้ในความคิดเห็นโดย @Quentin2
