Search code examples
typescriptconditional-types

Excluding function parameters by type in TypeScript


I would like to be able to take a function with n number of arguments and return a type based on that function where any argument with type x is no longer in the function type. For example:

function myTestFunction(email: string, context: TestContext, password: string): void {
  ...
}

I would like a type to use on that to create a function definition like this:

function myTestFunction(email: string, password: string): void {
  ...
}

I've managed to do it with this:

type Filter<T> = T extends [] 
  ? [] 
  : T extends [infer A, ...infer B] 
    ? A extends TestContext 
      ? Filter<B>
      : [A, ...Filter<B>]
    : T;
type ConvertFunction<T> = T extends (...args: any[]) => any
  ? (...args: Filter<Parameters<T>>) => ReturnType<T>
  : T;

The only problem is that the parameter names are lost and the signature becomes:

function myTestFunction(args_0: string, args_1: string): void {
  ...
}

How would it be possible to do this without losing the parameter names please?


Solution

  • Hmm, I don't think you can do this.

    What you can do is spread a tuple to preserve the names

    type MyTup = [a: string, b: number]
    type MyTup2 = [...MyTup] // [a: string, b: number]
    

    However, when you get a single value from a Tuple it will lose its name.

    type MyTup = [a: string, b: number]
    type MyTup2 = [MyTup[0], MyTup[1] // [string, string]
    

    And if you merge an unnamed member with a named tuple, all members become unnamed:

    type MyTup = [a: string, b: number]
    type B = [MyTup[0], ...MyTup] // [string, string, string]
    

    You could, of course, add names back in but there is no way I know of to actually get the name of a tuple member. So there's no way to do this generically.

    type B = [asdf: MyTup[0], qwerty: MyTup[1]] // [asdf: string, qwerty: string]
    

    All that means that when you do this:

    [A, Filter<B>]
    

    Then you are generating an unnamed tuple. And this recursive approach of re-re-re-constructing tuples is currently the only way to add or remove tuple members generically.


    So I could be wrong, but I'm not sure this is possible with the current version of typescript.