John Smith
John Smith

Reputation: 4343

Typescript - add one argument to a function's params

type SomeFunc = (a:string, b:number, c:someCustomType) => number;

I want to create a type that is just like the one above, except there is a single parameter added at the end. Let's say, d:number;

type SomeFuncAltered = (a:string, b:number, c:someCustomType, d:number) => number;

I do not want to craft the entire type manually though, I'm pretty sure there's a smart trick with Parameters<func> to be used here.

Upvotes: 18

Views: 10954

Answers (3)

Melody Universe
Melody Universe

Reputation: 261

As the accepted answer here doesn't seem to work for me (using TS 4), I wrote my own type that adds any number of parameters to the end of a function.

type AddParameters<
  TFunction extends (...args: any) => any,
  TParameters extends [...args: any]
> = (
  ...args: [...Parameters<TFunction>, ...TParameters]
) => ReturnType<TFunction>;

Usage:

type SomeFunc = (a: string, b: number, c: someCustomType) => number;
type SomeFuncAltered = AddParameters<SomeFunc, [d: number]>;
// SomeFuncAltered = (a:string, b:number, c:someCustomType, d:number) => number;

Note: This solution also allows you to add named parameters.

Upvotes: 21

Maciej Sikora
Maciej Sikora

Reputation: 20132

Its possible but quite sophisticated. More info can be found in this answer from @jcalz - Push type to the end of the tuple with skipping optional .

In your case we can reuse some utilities from above answer, exactly it would be Cons and Push and by using them make final type you need AddArgument. Consider:

type SomeFunc = (a: string, b: number, c: string) => number;

// some utility types for working with tuples
type Cons<H, T extends readonly any[]> =
    ((head: H, ...tail: T) => void) extends ((...cons: infer R) => void) ? R : never;

type Push<T extends readonly any[], V>
    = T extends any ? Cons<void, T> extends infer U ?
    { [K in keyof U]: K extends keyof T ? T[K] : V } : never : never;

// final type you need
type AddArgument<F, Arg> = 
F extends ((...args: infer PrevArgs) => infer R) 
? (...args: Push<PrevArgs, Arg>) => R : never

// function type with added boolean argument at the end
type NewFunction = AddArgument<SomeFunc, boolean>

Upvotes: 4

Oron Bendavid
Oron Bendavid

Reputation: 1533

You can use additional type for the base function args:

type FuncBaseArgs = {
  a: string;
  b: number;
  c: boolean;
}

type SomeFunc = ({...obj }: FuncBaseArgs) => number;

type SomeFuncAltered = ({...obj }: FuncBaseArgs, d: number) => number;

Upvotes: 2

Related Questions