Hot to rewrite the following javascript code in typescipt?
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 more than 100 functions in handlers which separated into several files, handlers provide apis for other modules, and the caller provide a unified entrance for these apis.
Every functions has been rewrite in typescipt correctly. But when came into the function caller, I'm confused, is there any way to rewrite it and keep the type info of callees?
I've made some attempts, but none work out at the end :( The following is one of them, may be close to the right solution.
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')