DEV Community

tmhao2005
tmhao2005

Posted on

Interesting TypeScript issue

I recently ran into the issue as following:

const actions = {
  call: (num: number) => {
    // todo
  },
  speak: (text: string) => {
    // todo
  },
}

// I'm going to create a function which can pass the action 
// and its corresponding argument as following:
doThings('call', 911);
doThings('speak', 'hello');

// so here the simple implemenatation
type Actions = typeof actions;
function doThings<T extends keyof Actions>(p0: T, ...[p1]: Parameters<Actions[T]>) {
  const action = actions[p0];
  // error!
  // Argument of type 'string | number' is not assignable to parameter of type 'never'.
  action(p1);
}
Enter fullscreen mode Exit fullscreen mode

As we can see, it has a typing issue as the comment. I quickly searched for solution, then I ended up following up this issue which was open long ago https://github.com/microsoft/TypeScript/issues/30581.

Looks like we haven't yet had a good solution for the issue though. I eventually came up with a solution after reading a few solutions/hackarounds from comments as following:

// create arguments map
type ArgsMap = {
  call: [num: number, message: string];
  speak: [message: string];
};

// this is a key where we have to define the type for the object
const actions: {[K in keyof ArgsMap]: (...p: ArgsMap[K]) => void} = {
  call: (num, message) => {
    // todo
  },
  speak: (text) => {
    // todo
  },
}
// eventually the function signature 
function getAcion<K extends keyof ArgsMap>(name: K, ...p: ArgsMap[K]) {
  const action = actions[name]
  // works!
  action(...p)
}
Enter fullscreen mode Exit fullscreen mode

Top comments (0)