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

การใช้โมดูลใน Meteor.js ด้วย Typescript


ทุกคน ผมกำลังพยายามทำสิ่งที่คิดว่าควรง่าย แต่ต้องมีบางอย่างที่ผมทำผิด ผมกำลังพยายามเพียงแค่มีโครงสร้างที่ชัดเจนในแอปพลิเคชัน Meteor ของผมที่ใช้ Typescript

นี่คือข้อกำหนดของฉัน:

  • อินเทอร์เฟซทั้งหมดสามารถใช้งานได้ทั้งในฝั่งไคลเอนต์และเซิร์ฟเวอร์
  • การใช้งานคลาสบางอย่างมีให้เฉพาะบนเซิร์ฟเวอร์เท่านั้น
  • ฉันไม่ต้องการพึ่งลำดับการโหลดไฟล์เพื่อให้แอปพลิเคชันของฉันทำงานได้อย่างถูกต้อง
  • ฉันต้องการโมดูลของตัวเองเพื่อไม่ให้ชนกับวัตถุทั่วโลก (เช่นคลาส Position เป็นตัวอย่าง)
  • ฉันต้องการมีไฟล์ include แบบโมโนลิธิกหนึ่งไฟล์สำหรับเซิร์ฟเวอร์ หนึ่งไฟล์สำหรับทั้งไคลเอนต์และเซิร์ฟเวอร์ และหนึ่งไฟล์สำหรับไคลเอนต์ (ไม่อยากมี include หลายสิบไฟล์อยู่ด้านบนของไฟล์ของฉัน)

การตั้งค่าที่ฉันมีอยู่ตอนนี้คือแบบนี้

  • เซิร์ฟเวอร์

    • เซิร์ฟเวอร์-หนังสือ.ts
  • ลูกค้า
  • ที่ใช้ร่วมกัน

    • collections.ts
  • คำนิยาม

    • เซิร์ฟเวอร์

      • include.d.ts (รวมไฟล์ .d.ts ทั้งหมดในโฟลเดอร์นี้)
      • เซิร์ฟเวอร์
      • include.d.ts (รวมไฟล์ .d.ts ทั้งหมดในโฟลเดอร์นี้)

      • server-book.d.ts (การใช้งานเฉพาะของหนังสือบนเซิร์ฟเวอร์)
    • ลูกค้า
    • ที่ใช้ร่วมกัน

      • include.d.ts (รวมไฟล์ .d.ts ทั้งหมดที่นี่)
      • book.d.ts (การกำหนดอินเทอร์เฟซของหนังสือ)
      • collections.d.ts

ในแต่ละไฟล์ .d.ts ที่ฉันมี

module MyModule {
     interface Bla {}
};

ในแต่ละไฟล์ .ts ที่กำหนดคลาส ฉันมี:

module MyModule {
     export class MyBla implements Bla {};
}

ไฟล์ .d.ts ทั้งหมดที่สร้างขึ้นสำหรับคลาสจะถูกสร้างโดย tsc -d

ไม่มีไฟล์ .ts ใดถูกรวมผ่าน ///<reference> แต่มีเพียงไฟล์ .d.ts เท่านั้น

ตอนนี้ เมื่อฉันเรียกใช้นี้ ฉันได้รับข้อผิดพลาดว่า MyModule ไม่ถูกกำหนด:

/// <reference path="shared/include.d.ts"/>
/// <reference path="server/include.d.ts"/>
Meteor.startup(() => {
   var temp = new MyModule.ServerBook();
});

ข้อผิดพลาดเกิดขึ้นตรงที่ MyModule

ฉันทำอะไรผิดหรือ? ควรตั้งค่าอย่างไรให้ถูกต้องที่นี่?

ขอบคุณ!

คำตอบ #1

ฉันได้จัดการกับปัญหานี้ในบล็อกของฉันแล้ว ฉันตัดสินใจที่จะใช้คำสั่งที่ชั่วร้าย eval เนื่องจากมันให้ความเป็นไปได้ที่ง่ายที่สุดในการใช้โมดูลจนกว่าจะมีบางสิ่งที่ซับซ้อนมากขึ้นปรากฏขึ้น

ไฟล์ /lib/foo.ts อยู่ในไดเรกทอรีย่อยเนื่องจากต้องถูกโหลดก่อน Bar

eval('var Hugo = (this.Hugo || (this.Hugo = {})'); // this will override the automatically emitted var Hugo and assigns it with globally defined Hugo module 

module Hugo {
  export class Foo {
    foo():string {
      return 'foo'
    }
  }
}

ไฟล์ /bar.ts

/// <reference path="lib/foo.ts"/>
eval('var Hugo = (this.Hugo || (this.Hugo = {})'); // this will override the automatically emitted var Hugo and assigns it with globally defined Hugo module 

module Hugo {
 export class Bar extends Foo {
    bar () : string {
      return 'bar';
    }
  }
}

ไฟล์ /test.ts

/// <reference path="lib/foo.ts"/>
/// <reference path="bar.ts"/>

var m = new Hugo.Bar();
console.log(m.bar());
console.log(m.foo());

ดังที่กล่าวไว้ที่นี่ สำหรับชั้นเรียน วิธีแก้ปัญหาก็ง่ายกว่านี้อีก:

class ExportedClass {
    variable : int;
} 
this.ExportedClass = ExportedClass;

คำตอบ #2

ไฟล์คำจำกัดความควรใช้คำสำคัญ declare โดยปกติคุณจะได้รับข้อผิดพลาดหากคุณไม่ได้ใช้คำสำคัญนี้

declare module MyModule {
     export interface Bla {}
}

และ

declare module MyModule {
    export class MyBla implements Bla {

    }
}

นอกจากนี้ยังควรตรวจสอบด้วยว่าคลาส ServerBook มีคำสำคัญ export หรือไม่ (เหมือนกับ MyBla ในตัวอย่างของคุณ)