9

If I have:

const selector = (state: {}, count = 1) => {};
type parms = Parameters<typeof selector>;

then parms will be:

[{}, number?]

I note if I apply an index I can extract a single param:

type parms = Parameters<typeof selector>[1]; // type parms = number

Is there some way to indicate I would like to omit the first parameter from being returned? Something along the lines of .slice(1)?

TOPKAT
  • 6,667
  • 2
  • 44
  • 72
Mister Epic
  • 16,295
  • 13
  • 76
  • 147
  • 2
    Possible duplicate of [typescript generic tuples error rest element](https://stackoverflow.com/questions/53356652/typescript-generic-tuples-error-rest-element) – jcalz Mar 25 '19 at 19:02

1 Answers1

15

For the specific case of "remove the first element from a tuple", you can use variadic tuple types as introduced in TypeScript 4.0:

type Tail<T extends any[]> = T extends [infer A, ...infer R] ? R : never;

Before 4.0 you could do it with generic rest parameters:

type Tail<T extends any[]> = 
  ((...x: T) => void) extends ((h: infer A, ...t: infer R) => void) ? R : never;

Either way gives you the desired behavior:

type Test = Tail<[1,2,3,4,5]>; // [2,3,4,5]
type Parms = Tail<Parameters<typeof selector>>; // [number?]

Playground link to code

jcalz
  • 264,269
  • 27
  • 359
  • 360
  • Thanks @jcalz, this works, but I admit I'm finding it a little dense. It appears that you infer the first param and then infer the rest with the spread, but to do so we must check to see if the `(...x: T) => void)` fat arrow function extends `(h: infer A, ...t: infer R) => void)` Is there somewhere where I can find this concept explained? – Mister Epic Mar 25 '19 at 19:12
  • This is using [type inference in conditional types](https://www.typescriptlang.org/docs/handbook/release-notes/typescript-2-8.html#type-inference-in-conditional-types) to pull out the rest type. We don't really want to do a check (we *know* that the check will pass); it's just that conditional types are the only handle TypeScript gives to perform such inference. – jcalz Mar 25 '19 at 19:15
  • What I especially like is that I can also adjust the above to `h: State` to ensure that the function I am `Tail`ing is conforming to my expectations about what the first parameter should be. Thanks again! – Mister Epic Mar 25 '19 at 19:19