تايب سكريبت: اسم طريقة الفئة كوسيط


أحاول إنشاء طريقة تستقبل كمعامل اسم طريقة معينة (كنص) لفئة معينة.

على سبيل المثال، إذا كان لدي هذا الكود:

class A {
    private member1: string;
    public member2: number;

    method1() {
        //something
    }

    method2() {
        //something
    }

    propMethod = () => {
        //prop method something
    }
}

type OnlyClassMethods<T> = T; // need the correct type here

const a = new A();
function callMethod(methodName: OnlyClassMethods<A>) {
    // methodName is of type "method1" | "method2"
    a[methodName](); // to call this
}

ثم سيتم حل methodName بشكل صحيح وسيعرف الإنتيليسنس أن هذه بالفعل طريقة من A. في الواقع، سأستخدم اسم الطريقة للاختبارات الوهمية، لذلك لن أقوم باستدعائها فعليًا (لذلك يجب أن يلتقط أي طريقة بغض النظر عن المعلمات المرسلة أو قيمة الإرجاع) لكني لا زلت أريد التأكد من أنها طرق موجودة فقط على الصف.

تحرير: تمكنت من حل مشكلتي الخاصة باستخدام كل من طرق الفئة وطرق الخاصية، لكن سأترك السؤال كما هو لأي شخص آخر. للحصول على حل يمكنه أيضًا التمييز بين النوعين، انظر حل كارول ماجيفسكي أدناه

الإجابة رقم 1

النوع الذي تحتاجه هو هذا:

type OnlyClassMethods<T> = {
    [K in keyof T]: T[K] extends (...args: any[]) => any ? K : never
}[keyof T]

callMethod('method1') // ok
callMethod('foo') // error
callMethod('member1')// error

هذا نوع مخطط شائع إلى حد كبير يستثني أسماء الخصائص غير الدالية.

ملعب

الإجابة رقم 2

من الممكن التمييز بين الطرق الصحيحة وخصائص الفئة، لكن ذلك يتطلب توضيحًا صريحًا لأنواع this. ضع في اعتبارك هذا المثال:

type FunctionPropertyOf<T> = {
    [P in keyof T]: T[P] extends Function
      ? P
      : never
}[keyof T]

type MethodOf<T> = {
    [P in keyof T]: T[P] extends (this: infer U) => any
      ? U extends T
        ? P
        : never
      : never
}[keyof T]

الاستخدام :

class Foo {
    bar(this: Foo) {}
    baz = () => {}
}

type T1 = FunctionPropertyOf<Foo> // "bar" | "baz"
type T2 = MethodOf<Foo>           // "bar"