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')