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

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

กรอกคำอธิบายรูปภาพที่นี่