ค้นหาเว็บไซต์

ข้อผิดพลาด 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

บทความที่เกี่ยวข้อง