typescriptkeyof

How to use [K in keyof X] in typescript to extract functions keys from a class?


I want to get a type that maps method names to their return values. The first step is to extract keys that represent methods of that class.

I tried this:

type ClassMethods<TClass> = {
    [K in keyof TClass] : TClass[k] extends (...args: any[])=>any ? "func" : never;
}

I asked an LLM and it gave me basically the same exact code. However, when I try it, the ClassMethods object contains all keys from the class, not just methods:

class TestClass {
    constructor(public test: string) {
        this.test = test;
    }
    public testMethod() {
        return this.test;
    }
    public async testMethodAsync() {
        return this.test;
    }
}

const testClassMethods = null as ClassMethods<TestClass>;
testClassMethods.[CTRL SPACE HERE]
                .test
                .testMethod
                .testMethodAsync

Screenshot from VS Code:

enter image description here

The reason I am doing this is that ultimately I want to generate a type that maps all sync methods to async but keeps async and async * methods as-is. This is to generate a type that represents remote side of an RPC client. Additionally I will be doing an intersection with a type that has list of methods that are allowed to be called by an RPC.

But in this question, I just want the above to work - the testClassMethods type should evaluate to:

{
    testMethod: "func",
    testMethodAsync: "func"
}

Solution

  • You need to use key remapping with as:

    type ClassMethods<TClass> = {
        [K in keyof TClass as TClass[K] extends (...args: any[]) => any ? K : never]: "func";
    };
    

    In the code above as TClass[K] extends (...args: any[]) => any ? K : never filters out non-method keys.

    I checked this version in VSCode and the autocomplete works correctly now.