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

ไทป์สคริปต์: อินสแตนซ์ของคลาสนามธรรม


ฉันมีคลาสนามธรรม Router:

export abstract class Router {
}

และอินเทอร์เฟซแบบนี้

interface IModule {
    name: string;
    forms: Array<IForm>,
    route: typeof Router
}

ตอนนี้ฉันมีคลาสหนึ่งซึ่งดูเหมือนแบบนี้ และมีหลายคลาสอื่น ๆ ที่อิงตาม Router abstract

export class Module1 extends Router {
}

ตอนนี้ ฉันต้องการสร้างอินสแตนซ์ของเส้นทางแบบนี้:

let module: IModule = { 
    name: "My Module",
    forms: [],
    route: Module1
}

let router = new module.route(); 
// TS2511: Cannot create an instance of an abstract class.

โค้ดทำงานได้ดี และตัวอย่างของ router=new Module1() ถูกสร้างขึ้นอย่างถูกต้อง แต่เห็นได้ชัดว่าฉันไม่ได้เขียนมันอย่างถูกต้องใน Typescript เพราะฉันเห็น TS2511: Cannot create an instance of an abstract class. เมื่อทำการแปลงโค้ด

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

คำตอบ #1

เมื่อคุณมีคลาสนามธรรม ตัวสร้างของมันสามารถเรียกใช้งานได้เฉพาะจากคลาสที่สืบทอดเท่านั้น เนื่องจากคลาสนี้เป็นนามธรรมและไม่ควรถูกสร้างอินสแตนซ์ ซึ่งสิ่งนี้ก็จะต่อเนื่องเมื่อคุณระบุชนิดบางอย่างเป็น typeof AbstractClass ตัวสร้างจะไม่สามารถเรียกใช้งานได้

วิธีแก้ปัญหาคือไม่ต้องใช้ typeof Router แต่ให้ใช้ลายเซ็นของตัวสร้าง (constructor) ที่คืนค่าเป็น Router

interface IModule {
    name: string;
    forms: Array<IForm>,
    route: new () => Router
}

อีกวิธีหนึ่งหากคุณต้องการเข้าถึงเมทอดสถิตของ Router คือการสร้างอินเทอร์เฟซที่สืบทอดจาก typeof Router ซึ่งจะลบความเป็นนามธรรมของคอนสตรัคเตอร์ออก:

export abstract class Router {
    static m(): void { console.log("Router"); }
}
type RouterClass = typeof Router;
interface RouterDerived extends RouterClass { }

interface IModule {
    name: string;
    route: RouterDerived
}

export class Module1 extends Router {
    static m(): void { console.log("Module1"); }
}

let module: IModule = { 
    name: "My Module",
    route: Module1
}

module.route.m();
let router = new module.route(); 

คำตอบ #2

หมายเหตุ ส่วนที่สองของคำตอบที่ยอมรับครอบคลุม:

ถ้าคุณต้องการเข้าถึงเมธอดสแตติกของ Router ...

วิธีแก้ปัญหาที่เสนอไม่ได้ผลจริง ๆ เพิ่งใช้เวลาพอสมควรในการพยายามหาวิธีแก้ไขเรื่องนี้ ดังนั้นคิดว่าควรเพิ่มว่า: วิธีทำสิ่งนี้คือ:

type RouterDerived = {new (): Router} & typeof Router;

สนามเด็กเล่นตัวอย่างเต็มรูปแบบ

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