Programmatically add methods to a class with type safety in TypeScript?

Clash Royale CLAN TAG#URR8PPPProgrammatically add methods to a class with type safety in TypeScript?
I'm writing a client for a web service, and one of the endpoints takes a single parameter from a possible 20 parameters (which could grow).
I expose a method for each of these possibilities on the client. Right now I'm doing it like this:
// keys.ts
export const FUNCTION_ONE = 'FunctionOne';
export const FUNCTION_TWO = 'FunctionTwo';
...
export const FUNCTION_TWENTY = 'FunctionTwenty';
// client.ts
import * as keys from './keys';
import { camelcase } from 'lodash';
export default class Client {
makeCall(method: string): Promise<void> {
// some implementation
}
}
Object.values(keys).forEach((key) => {
(Client.prototype as any)[camelcase(key)] = function () {
return this.makeCall(key);
};
});
Typescript knows nothing about the methods because they were added programmatically. I don't want to manually write each of these methods because the service might add more and I want it to be easy to just add them to the keys.ts file.
I was thinking of making a modification to the keys which would require me to type out the camelcase form of the key (an acceptable tradeoff) which I could then use to build a type which I could combine with the class. Something like this:
// keys.ts
function key<T extends string>(command: string, name: T) {
return { command, name };
}
export const FUNCTION_ONE = key('FunctionOne', 'functionOne');
...
// client.ts
export default class Client {
// same as before
}
interface ClientInterface<T extends Record<string, { name: string }>> {
// implementation??
}
export default type Client = ClientInterface<keys>;
How can I write this ClientInterface type which generates an interface with all the names from the keys as methods? Or is there a better way to do this entirely?
ClientInterface
By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.