Looking for a way to convert the following javascript code into typescript?
const handlers = {
say (msg) {
console.log(msg)
},
add (a, b) {
return a + b
}
}
function caller (method, ...args) {
if (handlers[method]) return handlers[methd](...args)
throw new Error(`${method} not found`)
}
I have a collection of more than 100 functions in handlers
spread across multiple files. These handlers
serve as APIs for other modules, while the caller
serves as a common entry point for these APIs.
All the functions have been successfully rewritten in typescript. However, when it comes to the caller
function, I am unsure about how to maintain type information for the callees.
Various attempts have been made, but none have proven successful in the end :( The solution below is one that shows promise.
type AlterReturnType<K, T extends (...args: any[]) => any> =
T extends () => any ? (k: K) => ReturnType<T> :
T extends (a: infer A) => any ? (k: K, a: A) => ReturnType<T> :
T extends (a: infer A, b: infer B) => any ? (k: K, a: A, b: B) => ReturnType<T> :
T extends (a: infer A, b: infer B, c: infer C) => any ? (k: K, a: A, b: B, c: C) => ReturnType<T> :
T extends (a: infer A, b: infer B, c: infer C, d: infer D) => any ? (k: K, a: A, b: B, c: C, d: D) => ReturnType<T> :
T extends (a: infer A, b: infer B, c: infer C, d: infer D, e: infer E) => any ? (k: K, a: A, b: B, c: C, d: D, e: E) => ReturnType<T> :
never
type Handlers = typeof handlers
type HandleKeys = keyof Handlers
interface IHandlerObject {
[k: string]: (...args: any[]) => any
}
type GetCaller<T extends IHandlerObject> = {
[k in keyof T]: AlterReturnType<k, T[k]>
}
type Caller = GetCaller<Handlers>[keyof Handlers]
const caller: Caller = function name (method: string, ...args: any[]) {
// do know how to rewrite the following
// @ts-ignore
if (handlers[method]) return handlers[method](...args)
throw new Error(`${method} not found`)
}
// TS error occurred:
// [ts] Cannot invoke an expression whose type lacks a call signature. Type '((k: "say", a: any) => void) | ((k: "add", a: any, b: any) => any)' has no compatible call signatures.
caller('say', 'ggg')