打字稿:类方法名称作为参数

时间:2018-12-26 11:38:56

标签: typescript

我正在尝试创建一个方法,该方法接收给定类的某些方法名称(作为字符串)作为参数。

例如,如果我有以下代码:

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的方法。 实际上,我将使用方法名称进行模拟,因此我并没有真正调用它(因此,无论参数传递或返回值如何,此方法都应捕获任何方法),但我仍要确保它仅存在于方法上班级。

编辑:我设法通过类方法和属性方法来解决我的特定问题,但是我将把这个问题留给其他人。有关还可以区分这两种类型的解决方案,请参见下面的Karol Majewski's解决方案

2 个答案:

答案 0 :(得分:3)

您需要的类型是:

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

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

这是一个非常普遍的mapped type,其中排除了非功能性属性名称。

Playground

答案 1 :(得分:1)

可以在适当的方法和类属性之间进行区分,但是它需要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"