I’ve been stuck on this for a while without being able to find an elegant solution.
I have a Enum:
export enum Enum {
A,
B,
C,
}
Then an object that uses said Enum, the structure is relatively known, as it’s value will always be a function which will return a string, but the unknown thing is that the function may take any amount of args:
import { A, B, C } from '../enums/';
export const obj = {
[A]: () => 'example 1',
[B]: (arg1: string) => 'example 2, arg1: %s',
[C]: (nr: string, arg2: string) => 'example %s %s',
}
Last part of the structure is a function, which makes use of obj to retrieve certain strings based on it’s args:
const fct = <E extends Enum>(
code: E,
...args: Parameters<(typeof obj)[E]>
) => {
...
}
Everything works, but it is not type-safe, as I require every Enum value to be assigned to a value inside of obj.
If I were to create a basic type, Parameter would not display the proper arguments of the function:
type ObjectType = { [key in Enum]: (...args: any[]) => string }
Parameters<(typeof obj)[A]> // -> (...args: any[])
>Solution :
You can constrain the type of obj to only allow keys of Enum and values of "functions that return string" using the satisfies operator (see also the type utility Record<Keys, Type>), and you can constrain the generic type parameter E in the function fct by the actual keys of obj rather than any Enum (which might or might not be present as a key) like this:
enum Enum {
A,
B,
C,
}
const obj = {
[Enum.A]: () => 'example 1',
[Enum.B]: (arg1: string) => 'example 2, arg1: %s',
[Enum.C]: (nr: string, arg2: string) => 'example %s %s',
} satisfies Record<Enum, (...args: any[]) => string>;
const fct = <E extends keyof typeof obj>(
code: E,
...args: Parameters<(typeof obj)[E]>
) => {};
fct(Enum.A); // Ok
fct(Enum.A, "foo"); /* Error (expected)
~~~~~
Expected 1 arguments, but got 2.(2554) */
fct(Enum.B, "foo"); // Ok
fct(Enum.B); /* Error (expected)
~~~~~~~~~~~
Expected 2 arguments, but got 1.(2554) */
fct(Enum.C, "foo", "bar"); // Ok
fct(Enum.C, "foo"); /* Error (expected)
~~~~~~~~~~~~~~~~~~
Expected 3 arguments, but got 2.(2554) */
fct(Enum.C); /* Error (expected)
~~~~~~~~~~~
Expected 3 arguments, but got 1.(2554) */
// …etc.