18

I have a possibly weird situation that I'm trying to model with typescript.

I have a bunch of functions with the following format

type State = { something: any }


type InitialFn = (state: State, ...args: string[]) => void

I would like to be able to create a type that represents InitialFn with the first argument removed. Something like

// this doesn't work, as F is unused, and args doesn't correspond to the previous arguments
type PostTransformationFn<F extends InitialFn> = (...args: string[]) => void

Is this possible?

MDalt
  • 1,681
  • 2
  • 24
  • 46
  • I don't understand typescript much, but *InitialFn with the first argument removed*, isn't it completely another function? – apple apple Nov 08 '19 at 10:38
  • In normal js if you want to remove the need to provide leading arguments you can use bind() to set arguments to pass when the returned function is called, ie `a=(b,c)=>{}; d=a.bind(null,6);` such that calling `d(7)`, `b` will always be `6` and `c` will be whatever the first passed arg to `d` was 7 in this case. Not sure what the ts syntax would be for this – Patrick Evans Nov 08 '19 at 10:44

3 Answers3

28

I think you can do that in a more generic way:

type OmitFirstArg<F> = F extends (x: any, ...args: infer P) => infer R ? (...args: P) => R : never;

and then:

type PostTransformationFn<F extends InitialFn> = OmitFirstArg<F>;

PG

georg
  • 211,518
  • 52
  • 313
  • 390
5

You can use a conditional type to extract the rest of the parameters:

type State = { something: any }

type InitialFn = (state: State, ...args: string[]) => void

// this doesn't work, as F is unused, and args doesn't correspond to the previous arguments
type PostTransformationFn<F extends InitialFn> = F extends (state: State, ...args: infer P) => void ? (...args: P) => void : never

type X = PostTransformationFn<(state: State, someArg: string) => void> // (someArg: string) => void

Playground Link

Titian Cernicova-Dragomir
  • 230,986
  • 31
  • 415
  • 357
1

I've landed on this question a few times now because I can never remember the name of the OmitThisParameter<Type> utility exported from Typescript as of version 3.3. The OmitThisParameter<Type> is not as generic as the solution posted by @georg, but has always been what I've been looking for when I stumble across this question. Hopefully someone else finds this helpful as well (at the bare minimum I'll see it next time I forget the name of the utility)

jdk905
  • 495
  • 5
  • 11