تايب سكريبت - الحصول على خصائص الكلاس


هل هناك طريقة للحصول على أسماء الخصائص للفئة في TypeScript؟

في المثال، أود أن 'أصف' الفئة A أو أي فئة وأحصل على مصفوفة من خصائصها (ربما فقط العامة منها؟)، هل هذا ممكن؟ أم يجب أن أقوم بإنشاء الكائن أولاً؟

class A {
    private a1;
    private a2;
    /** Getters and Setters */

}

class Describer<E> {
    toBeDescribed:E ;
    describe(): Array<string> {
        /**
         * Do something with 'toBeDescribed'                          
         */
        return ['a1', 'a2']; //<- Example
    }
}

let describer = new Describer<A>();
let x= describer.describe();
/** x should be ['a1', 'a2'] */ 

الإجابة رقم 1

كود TypeScript هذا

class A {
    private a1;
    public a2;
}

يتم تجميعه إلى هذا الكود جافا سكريبت

class A {
}

هذا لأن الخصائص في جافاسكريبت تبدأ بالوجود فقط بعد أن يكون لها قيمة ما. عليك أن تعطي الخصائص بعض القيمة.

class A {
    private a1 = "";
    public a2 = "";
}

يترجم إلى

class A {
    constructor() {
        this.a1 = "";
        this.a2 = "";
    }
}

مع ذلك، لا يمكنك الحصول على الخصائص من الصف فقط (يمكنك الحصول على الدوال فقط من النموذج الأولي). يجب عليك إنشاء نسخة. ثم يمكنك الحصول على الخصائص عن طريق استدعاء Object.getOwnPropertyNames().

let a = new A();
let array = return Object.getOwnPropertyNames(a);

array[0] === "a1";
array[1] === "a2";

مطبق على مثالِك

class Describer {
    static describe(instance): Array<string> {
        return Object.getOwnPropertyNames(instance);
    }
}

let a = new A();
let x = Describer.describe(a);

الإجابة رقم 2

بعض الإجابات خاطئة جزئياً، وبعض الحقائق فيها خاطئة جزئياً أيضاً.

أجب عن سؤالك: نعم! يمكنك.

في تايب سكريبت

class A {
    private a1;
    private a2;


}

ينشئ الشيفرة التالية في جافاسكريبت:

var A = /** @class */ (function () {
    function A() {
    }
    return A;
}());

كما قال @Erik_Cupal، يمكنك فقط أن تفعل:

let a = new A();
let array = return Object.getOwnPropertyNames(a);

لكن هذا غير مكتمل. ماذا يحدث إذا كان لدى صفك منشئ مخصص؟ تحتاج إلى القيام بخدعة مع Typescript لأنه لن يتم تجميعه. تحتاج إلى التعيين كـ any:

let className:any = A;
let a = new className();// the members will have value undefined

الحل العام سيكون:

class A {
    private a1;
    private a2;
    constructor(a1:number, a2:string){
        this.a1 = a1;
        this.a2 = a2;
    }
}

class Describer{

   describeClass( typeOfClass:any){
       let a = new typeOfClass();
       let array = Object.getOwnPropertyNames(a);
       return array;//you can apply any filter here
   }
}

للفهم الأفضل، سيشير هذا اعتمادًا على السياق.

الإجابة رقم 3

حل آخر، يمكنك ببساطة التكرار على مفاتيح الكائن هكذا، ملاحظة: يجب عليك استخدام كائن مُنشأ يحتوي على خصائص موجودة:

printTypeNames<T>(obj: T) {
    const objectKeys = Object.keys(obj) as Array<keyof T>;
    for (let key of objectKeys)
    {
       console.log('key:' + key);
    }
}

الإجابة رقم 4

مجرد للمرح

class A {
    private a1 = void 0;
    private a2 = void 0;
}

class B extends A {
    private a3 = void 0;
    private a4 = void 0;
}

class C extends B {
    private a5 = void 0;
    private a6 = void 0;
}

class Describer {
    private static FRegEx = new RegExp(/(?:this\.)(.+?(?= ))/g); 
    static describe(val: Function, parent = false): string[] {
        var result = [];
        if (parent) {
            var proto = Object.getPrototypeOf(val.prototype);
            if (proto) {
                result = result.concat(this.describe(proto.constructor, parent));
            } 
        }
        result = result.concat(val.toString().match(this.FRegEx) || []);
        return result;
    }
}

console.log(Describer.describe(A)); // ["this.a1", "this.a2"]
console.log(Describer.describe(B)); // ["this.a3", "this.a4"]
console.log(Describer.describe(C, true)); // ["this.a1", ..., "this.a6"]

تحديث: إذا كنت تستخدم مُنشئات مخصصة، فإن هذه الوظيفة ستتوقف عن العمل.