javascript - คืนตัวสร้างของประเภททั่วไปใน TypeScript
ฉันกำลังพยายามหาวิธีเขียนโค้ด TypeScript ที่ระบุว่าฟังก์ชันนั้นคืนค่า constructor ของประเภท generic มีตัวอย่างมากมายเกี่ยวกับวิธีการส่ง constructor ของประเภท generic แต่ไม่ใช่วิธีการคืนค่า
โปรดตรวจสอบตัวอย่างต่อไปนี้:
นี่คือส่วนหนึ่งของคลาสนามธรรม:
getModel(): (new () => T) {
throw new Error('Method not implemented.'); // Error because don't know how to fix it
}
เมื่ออยู่ในคลาสย่อย ฉันกำลังพยายามใช้งานมันแบบนี้:
getModel(): typeof User {
return User;
}
ฉันมีข้อผิดพลาดดังต่อไปนี้:
Type '() => typeof User' is not assignable to type '() => new () => User'.
ฉันสามารถข้ามการนำไปใช้ในคลาสที่สืบทอดได้ถ้าฉันรู้วิธีระบุในคลาสนามธรรม
ดังนั้นคำถามคือ - จะระบุได้อย่างไรในระดับคลาสเชิงนามธรรมว่าฟังก์ชันจะคืนค่าคอนสตรัคเตอร์ของประเภทเจเนอริก และฉันสามารถข้ามการใช้งานของฟังก์ชันนี้ในคลาสลูกได้หรือไม่? หรือบางทีฉันระบุลายเซ็นการคืนค่าไม่ถูกต้องในระดับคลาสเชิงนามธรรม?
แก้ไข:
กรุณาตรวจสอบปัญหาที่แปลก Class A และ B แตกต่างกันเพียงการมีตัวสร้างแบบชัดเจน และใน RealA ไม่ทำงานแต่ RealB ทำงานได้เหมือนกันกับเมธอด getModel()
class A {
a = '';
constructor(a: string) {
}
}
class B {
a = '';
static test(): void {
console.log('I do work');
}
}
abstract class Base<T> {
Prop: T;
constructor(TCreator: { new (): T; }) {
this.Prop = new TCreator();
}
getModel(): (new () => T) {
throw new Error('Method not implemented.'); // Error because don't know how to fix it
}
}
class RealA extends Base<A> {
getModel(): typeof A { // doesn't work - compilation error
return A;
}
}
class RealB extends Base<B> {
getModel(): typeof B { // works
return B;
}
}
var test = new RealA(A); // compile error
var test2 = new RealB(B)
สำหรับคลาส RealA เกิดข้อผิดพลาดเดียวกัน
() => typeof A' is not assignable to type '() => new () => A'
คำตอบ #1
ข้อผิดพลาดนี้เป็นสิ่งที่คาดไว้เนื่องจากตัวสร้างของคลาส A มีอาร์กิวเมนต์ที่จำเป็น คลาสนามธรรมจำกัดให้ตัวสร้างต้องไม่มีอาร์กิวเมนต์ (new() => T)
วิธีแก้ปัญหาแบบง่ายคือการลบคอนสตรัคเตอร์ของ A
ถ้าคุณต้องการที่จะสามารถส่งผ่านในคลาสที่มีคอนสตรัคเตอร์ซึ่งต้องการอาร์กิวเมนต์ คุณจะต้องเปลี่ยนคำจำกัดความของคลาสฐานเพื่อจับประเภทคอนสตรัคเตอร์ และให้ constructor รับอาร์กิวเมนต์ที่จำเป็นเหล่านั้น (โดยใช้ทูเพิลในพารามิเตอร์ที่เหลือ)
class A {
a = '';
constructor(a: string) {
}
}
class B {
a = '';
static test(): void {
console.log('I do work');
}
}
type ArgumentTypes<T> = T extends new (...a: infer A) => any? A : []
abstract class Base<T extends new (...a: any[])=> any> {
Prop: InstanceType<T>;
constructor(TCreator: T, ...a: ArgumentTypes<T>) {
this.Prop = new TCreator(...a);
}
getModel(): T {
throw new Error('Method not implemented.'); // Error because don't know how to fix it
}
}
class RealA extends Base<typeof A> {
getModel(): typeof A { // doesn't work - compilation error
return A;
}
}
class RealB extends Base<typeof B> {
getModel(): typeof B { // works
return B;
}
}
var test = new RealA(A, ""); // ok
var test2 = new RealB(B)
