【问题标题】:Typescript: class method name as argument打字稿:类方法名称作为参数
【发布时间】:2018-12-26 11:38:56
【问题描述】:

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

例如,如果我有这个代码:

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 解决方案

【问题讨论】:

    标签: typescript


    【解决方案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
    

    这是一个非常常见的mapped type,不包括非函数属性名称。

    Playground

    【讨论】:

    • 我知道 methodName 的类型是:"member2" | “方法1” | “方法2” | “propMethod”,而我只是在寻找方法
    • 我错过了您想将“方法”与“具有函数值的成员”分开的部分。但这是一个错误的目标。它们都是任何第三方的方法,从那个角度来看绝对没有区别。因此,我不知道您要达到什么目的以及为什么。这是不可能的,也不应该这样做。
    • 你的答案是正确的,我忘了在 member1/member2 上放置一个不是“任何”的类型。在我的场景中,由于我在使用反应测试套件时遇到问题,我还试图将“打字稿”属性与方法区分开来。
    • @Jellof 很高兴我能帮上忙!
    【解决方案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"
    

    【讨论】:

    • +1,这确实具有区分它们的价值,因为您不能将“this:MyClass”放在属性方法中。
    猜你喜欢
    • 2023-01-14
    • 2018-01-26
    • 1970-01-01
    • 2023-01-17
    • 2022-11-11
    • 1970-01-01
    • 2022-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多