angular - มีวิธีใดบ้างในการรับประเภทที่ประกาศของสมบัติ แทนที่จะเป็นประเภทของค่าที่ถูกกำหนดใน TypeScript
ฉันกำลังพยายามสร้างคลาสโมเดลทั่วไปใน TypeScript ที่สามารถถูกสืบทอดโดยโมเดลลูกเพื่อวัตถุประสงค์ในการสร้างวิธีการประมวลผลข้อมูล HTTP ไปยังโมเดลโดยอัตโนมัติในซูเปอร์คลาส
แบบจำลองเด็กพื้นฐานอาจเป็นดังนี้:
export class User extends Model {
private username: string = null;
constructor () {
super ();
this.processJson ();
}
}
ด้วยคลาส Model ต้นแบบของเราที่ทำอะไรบางอย่างเช่น:
export class Model {
constructor () {
}
public processJson<T> () {
_.forEach (Object.keys (this), (key: string) => {
console.log (`processing key: ${key}`);
console.log (typeof this[key]);
})
}
}
แผนคือการใช้วิธี processJson เป็นจุดเข้าเดียวเพื่อรับข้อมูล JSON เข้ามาและประมวลผลให้เป็นโมเดลย่อยของเราตามข้อกำหนดของพวกมัน
ปัญหาที่นี่คือดูเหมือนว่าฉันไม่สามารถรับประเภทที่ประกาศไว้ซึ่งถูกกำหนดในโมเดลลูกได้ ในตัวอย่างที่ให้มา typeof this[key] จะคืนค่า object เนื่องจากมันสรุปประเภทของค่าที่กำหนด ในตัวอย่างนี้คือ null.
แผนของฉันคือการใช้สิ่งนี้สำหรับกรณีที่ซับซ้อนมากขึ้นซึ่งเราอาจมีวัตถุที่ซับซ้อนมากขึ้นหรือประเภทต่าง ๆ ที่มีการประมวลผลพิเศษและทำทั้งหมดในที่รวมศูนย์ภายในคลาส Model พ่อแม่ของเรา
คำถามของฉันคือ ดังนี้ ฉันสามารถรู้จักคุณสมบัติของโมเดลลูกนั้นอย่างไร เพื่อให้ได้ประเภทที่ประกาศของตัวอย่างของเรา username เป็น string ไม่ใช่ object ?
นี่เป็นข้อจำกัดของ JavaScript พื้นฐานที่ถูกสร้างขึ้นหรือไม่? หรือฉันกำลังเข้าใจผิดเกี่ยวกับวิธีการทำงานของคุณสมบัติของคลาสที่ประกาศใน Typescript?
ฉันรู้ว่าเมื่อประกาศคุณสมบัติเป็น:
private username: string = '';
มันจะให้ประเภทที่ถูกต้องกับฉัน แต่ฉันไม่ต้องการกำหนดค่าเริ่มต้นจนกว่าค่าจะถูกกำหนดโดยข้อมูล JSON เพราะในบางกรณี null อาจเป็นค่าที่ถูกต้อง
คำตอบ #1
โค้ดตัวอย่างของคุณสมมติว่าคุณต้องการข้อมูลประเภทของ TypeScript ในเวลารันไทม์ อย่างไรก็ตาม ในเวลารันไทม์ ประเภททั้งหมดจะถูกลบโดยคอมไพเลอร์ของ TypeScript มันเพียงแค่สร้าง JavaScript ธรรมดาโดยไม่มีคำอธิบายประเภท
ฉันเชื่อว่าทางเลือกที่ดีที่สุดของคุณคือการสร้างตัวตกแต่ง (decorator) และตกแต่งทุกคุณสมบัติของโมเดลด้วยมัน - แบบนี้:
class User extends Model {
@ModelField private username: string;
}
นอกจากนี้ให้แน่ใจว่าคุณเปิดใช้งานตัวเลือกคอมไพเลอร์ emitDecoratorMetadata (https://www.typescriptlang.org/docs/handbook/decorators.html#metadata)
มันควรอนุญาตให้คุณอ่านประเภทของคุณสมบัติที่ตกแต่งผ่าน reflect-metadata (เช่น ตามที่แนะนำในคำตอบนี้: วิธีรับข้อมูลประเภทใน TypeScript decorator?)
คำตอบ #2
คุณสามารถตรวจสอบชนิดที่ประกาศโดยใช้ typeof การเปรียบเทียบแบบเข้มงวด === และ instanceof
กรอกคำอธิบายรูปภาพที่นี่
