A common, widely-documented pattern is to specify the parameter type for a function with a generic, like so:
type Func<T> = (arg: T) => void;
let example : Func<boolean>; // function(arg: boolean)
However, I'm trying to declare parameters of varying numbers and types with a single generic. One method that I tried is to use arrays containing the types, like this:
type Func<T extends Array<any>> = (...arg: T) => void;
let example : Func<[string, number]>; // function(arg_0: string, arg_1: number)
The problem with this is shown in the comment above – the parameters are given generic names in code hinting, which isn't ideal. In order to add names to my parameters, I came up with the idea of using an object for the generic:
type Func<T extends Object> = (...arg: T) => void; // Error: A rest parameter must be of an array type.
let example : Func<{ a: string, b: number }>; // Goal: function(a: string, b: number)
The goal is for example to look like function(a: string, b: number), with the parameter names (a and b) included in code hinting. But this code errors because T must be an array for the spread operator. I'm having trouble finding a way to convert the object into an array, or an alternative method of applying it to the function parameters.
I tried using keyof which resulted in a union type, but I'm not sure if a union type can be converted to an array while keeping that name association.
Is this even possible? I've seen some code hinting magic with the TS server and VS Code where it kept name associations even though logically they should be lost. If so, what is the most direct way to convert { a: string, b: number } into (a: string, b: number) => void using a single generic?
<...T>would not allow me to name the parameters, which is what I'm ultimately looking for. I can achieve the desired functionality using arrays, but they do not have parameter names, so I'm just curious about the possibility of converting an object to a tuple in hopes that the parameters are named according to the object's keys.<[{a:string}, {b:number}]>would this satisfy you? I think what you want to achieve is not possible in current TS. Also its very limited in the use as if you can use just one argument as an record and you have what you want without spread operator.