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

TypeScript - ใช้คลาสเป็นทั้งคอนสตรัคเตอร์และประเภท


ฉันมีคลาสที่ชื่อว่า Model ซึ่งห่อหุ้มคลาส schema อย่างเช่น "Person" และสามารถสร้างอินสแตนซ์ได้สำเร็จดังนี้:

 const people = new Model<Person>(Person, db);

DB เป็นการสร้างนามธรรมให้กับฐานข้อมูลและอนุญาตให้โมเดลสื่อสารกับฐานข้อมูลโดยไม่ต้องรู้รายละเอียดของ DB ... มันอาจจะไม่สำคัญมากสำหรับคำถามนี้ แต่ฉันหยิบขึ้นมาพูดเพราะมันดูสำคัญอย่างยิ่ง

ความซ้ำซ้อนของการส่งคลาส Person สองครั้งนั้นน่ารำคาญและฉันคิดว่าฉันอาจจะสามารถสร้างเมธอดสแตติกจาก Model ที่เรียกว่า create() ซึ่งมีลักษณะดังนี้:

public static create(schema: new () => any, options: IModelOptions = {}) {
  const schemaClass = new schema();
  const db = options.db || Model.defaultDb;
  const logger = options.logger || baseLogger;
  const model = new Model<typeof schema>(schema, db, logger);
  return model;
}

ซึ่งฉันสามารถสร้างอินสแตนซ์ได้อย่างง่ายดายด้วย:

 const people = Model.create(Person, { db });

นี่เกือบจะดูเหมือนว่ามันได้ผล แต่ดูเหมือนว่า Typescript จะเข้าใจประเภททั่วไปที่ใช้สำหรับ Model ผิดเล็กน้อย ฉันกำลังเข้าใจผิดอยู่หรือไม่? มีวิธีที่จะทำในสิ่งที่ฉันต้องการทำหรือไม่? ถ้าใช่ ฉันทำอะไรผิด?

เพื่อให้รายละเอียดเพิ่มเติมเกี่ยวกับสิ่งที่ ไม่ ทำงาน ... ผมพบว่าข้อมูลประเภททั่วไปที่ส่งเข้ามาเป็น "T":

 export default class Model<T extends BaseSchema> { ... }

ไม่ได้พิมพ์สิ่งต่าง ๆ อย่างถูกต้อง ดังนั้นตัวอย่างเช่น ส่วนติดต่อสาธารณะหลายส่วนของ Model จำกัดข้อมูลนำเข้าให้เป็นชนิด <T> แต่แทนที่จะเป็น "Person" กลับถูกแก้ไขเป็นฟังก์ชันตัวสร้างสำหรับ Person: new() => any ซึ่งดูเหมือนไม่จำกัดอะไรเลย

คำตอบ #1

คุณควรทำให้ create เป็นแบบทั่วไปด้วยเช่นกัน และให้คอมไพเลอร์คาดเดาประเภทอินสแตนซ์ตามประเภทการคืนค่าของคอนสตรัคเตอร์ ตอนนี้คุณกำลังสร้าง Model<typeof Person> โดยที่คุณต้องการ Model<Person>:

class Model<T> {
    public constructor(schema: T) {}
    public static create<T>(schema: new () => T) {
        const schemaClass = new schema();
        const model = new Model<T>(schemaClass);
        return model;
    }
}

class Person {}

let personModel = Model.create(Person) // will be Model<Person>