I want to create a registry of different functions in Typescript.
For example I have several functions with different arguments types:
const func1 = (p: { x: number }) => {
console.log("number: " + p.x);
};
const func2 = (p: { s: string }) => {
console.log("string: " + p.s);
};
I create a registry with them and giving them names:
const map = {
number: func1,
string: func2
};
Then I want to infer following type:
{ funcName: "number", x: number } | { funcName: "string", s: string }
This type holds the information about function name in registry and its arguments type. I can do this automatically by following code:
type Keys = keyof typeof map;
// assume all functions have single input argument
type ArgByName<Key extends Keys> = Parameters<typeof map[Key]>[0];
type ArgExtendedByName<Key extends Keys> = ArgByName<Key> & { funcName: Key };
type ArgType = { [Key in Keys]: ArgExtendedByName<Key> }[Keys];
Finally I write a function to call functions from registry:
function Apply(args: ArgType) {
const { funcName, ...funcArgs } = args
map[funcName](funcArgs);
}
But I get the following error:
Argument of type "{ s: string; } | { x: number; }" is not assignable to parameter of type "{ x: number; } & { s: string; }".
Type "{ s: string; }" is not assignable to type "{ x: number; } & { s: string; }".
Property 'x' is missing in type '{ s: string; }' but required in type '{ x: number; }'.ts(2345)
index.ts(1, 21): 'x' is declared here.
I really cannot understand, why the input arguments of functions became this { x: number; } & { s: string; }
, but not this { s: string; } | { x: number; }"
. Is it Typescript bug or my error? How does this problem can be solved?
Also here is a playground with all code above: https://codesandbox.io/s/sad-mccarthy-nvb47?fontsize=14&hidenavigation=1&theme=dark
See Question&Answers more detail:
os 与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…