Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

Make similar function but exclude the last argument

I’m trying to create a type B which defines same function as type A but omits the last parameter. I’ve tried the following but it still asks for 2 parameters.

type Callback = (msg: string) => void;

type A = (A: string, B: Callback) => void;
type B = <U extends Exclude<Parameters<A>, Callback>>(...args: U) => void;

const b: B = (...args) => {};

b("some string"); // Expected 2 arguments, but got 1.

How can I do this properly?

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

>Solution :

You can use conditional type inference to exclude the last parameter from a function type:

type ExcludeLastParam<T extends (...args: any) => any> =
    T extends (...args: [...infer I, any]) => infer R ? (...args: I) => R : never;

This matches T against (...args: [...I, any]) => R for some I and R that the compiler infers using the infer keyword. Note that [...I, any] is a variadic tuple type and by matching [...I, any] against a tuple type (like, say, [a: string, b: Callback]), the compiler will infer I to be the "initial" part of the tuple excluding the last entry (since the any type will match anything) (like, say, [a: string]).

Let’s test it out:

type Callback = (msg: string) => void;   
type A = (a: string, b: Callback) => void;

type B = ExcludeLastParam<A>;
// type B = (a: string) => void

And

type C = (a: string, b: number, c: boolean, d: Date) => string;
type D = ExcludeLastParam<C>
// type D = (a: string, b: number, c: boolean) => string

Looks good!


Note that your version doesn’t work because, while the Parameters<T> utility type can be used to extract the parameter list as a tuple type, the Exclude<T, U> utility type does not filter tuple types; instead it filters union types. Since Parameters<A> is of type [a: string, b: Callback], filtering out Callback isn’t going to do anything (because Parameters<A> is not a union… or maybe it’s a single member union, and that member is not assignable to Callback).

Playground link to code

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading