Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is there some way to "spread" object properties to parameters of a function definition?

Best explained in code:

const ROUTE_PARAMS = {
  userId: 'userId',
  companyId: 'companyId',
};

// Is this somehow possible?
// `typeof` is obviously not the right tool here, just used as an example.
function buildRoute(typeof ROUTE_PARAMS): string;

// Result should be similar to:
function buildRoute2(userId: string, companyId: string): string;

// 🟩 The function should be called like this:
buildRoute('some-user-id', 'some-company-id');

// 🟥 I don't want the function to accept only 1 object like this:
buildRoute({ userId: 'some-user-id', companyId: 'some-company-id' });

The idea is to have the route params of buildRoute somehow dynamically "bound" to the object. When defining the function params "manually" (like in buildRoute2), I always have to keep them in sync when changing properties of ROUTE_PARAMS...


Additional Info

I'll try to add some information as my question above does not seem to be sufficiently clear:

  • I'm explicitly looking for a way to "type" this function from an object like the one shown above (ROUTE_PARAMS).
  • I can't change this to some other structure (tuple type, some kind of array, ...) as that would require refactoring of other parts in my code which work with the object ROUTE_PARAMS.
  • The function should except each object property as a single input parameter (i.e. function arity === number of object properties).
    I don't want the function to accept all properties packed into 1 object (🟩 & 🟥 examples above).
like image 581
suamikim Avatar asked Nov 06 '25 12:11

suamikim


1 Answers

At first, I thought what you want would be easily possible by using the spread operator with a tuple type. For instance,

function f(...args: [string, string]) {}

is (except of the parameter names) the same as

function f(arg0: string, arg1: string) {}

So we could try:

const ROUTE_PARAMS = {
  userId: 'userId',
  companyId: 'companyId',
};

function buildRoute(...args: typeof ROUTE_PARAMS[keyof typeof ROUTE_PARAMS][]): void {}

However, typeof ROUTE_PARAMS[keyof typeof ROUTE_PARAMS][] is an array, so that we could supply an arbitrary number of arguments to the resulting buildRoute function. It would be effectively the same as when you wrote function buildRoute(...args: string[]). Also, when the values are not only strings, but, for instance, a number was included, the inferred type would be (string | number)[] and we could supply a number at any position.

The difference to f above is that the type of the spread variable is a tuple for f but an array for buildRoute. So we would need to get a tuple out of the values of ROUTE_PARAMS. But, unfortunately, that is not supported and will not be, as a corresponding proposal was declined: https://github.com/microsoft/TypeScript/issues/13298.

So I now think that what you want is probably not possible with TypeScript.

like image 148
Remirror Avatar answered Nov 09 '25 08:11

Remirror



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!