hyde
hyde

Reputation: 2585

TypeScript reusable function arguments type

I have a function that is defined as so:

function getRangeBounds(start: number, stop?: number, step?: number) {
  if (step === undefined) step = 1;
  const actualStart = start !== undefined && stop !== undefined ? start : 0;
  const actualStop = stop === undefined ? start : stop;
  return [actualStart, actualStop, step];
}

I want this function's arguments to be typed and be reusable. So I did:

type Range = Parameters<typeof getRangeBounds>;

I want the type Range to be reusable across a couple more functions, namely range and mapRange that will have the following signatures respectively:

export function range(...args: Range): ReadonlyArray<number> {
  /* this will call getRangeBounds at some point */
}

export function mapRange(...rangeArgs: Range, mapper: MapFunc<number> = IdentityMapper) {
  return range(rangeArgs).map(mapper); /* code does not compile */
}

How can I make these functions behave in a way the contract Range is honored by them all and also be possible to use extra args in some functions like the mapRange above?

Edit: I fixed the compilation error above, so mapRange looks like this now:

export function mapRange(rangeArgs: Range, mapper: MapFunc<number>) {
  return range(...rangeArgs).map(mapper);
}

But I now need to call the function like this:

mapRange([start, stop, step])

Upvotes: 3

Views: 1605

Answers (1)

ford04
ford04

Reputation: 74500

Some options to add extra parameters to Range for other functions:

Option 1: Change rest parameter to be the last element
function mapRangeRest(mapper: MapFunc<number>, ...rangeArgs: Range) { ... }

mapRangeRest(mapFunc, 1)
mapRangeRest(mapFunc, 1, 2)
Option 2: Currying
function mapRangeCurry(...rangeArgs: Range_): (mapper: MapFunc<number>) { ... }

mapRangeCurry(1)(mapFunc)
mapRangeCurry(1, 2)(mapFunc)
Option 3 (TS 4.0): Variadic tuples
function mapRangeVT<T extends Range_>(...rangeArgs: [...T, MapFunc<number>]) {...}

mapRangeVT(1, mapFunc)
mapRangeVT(1, 2, mapFunc)

If you can update to the latest TS version, option 3 probably fits best, as function shape is not changed.

Play sample

Upvotes: 2

Related Questions