0

Imagine that I have a function that behaves differently when passed one parameters vs two. For example:

function test(a: string | number, b?: number ) {
  if(typeof b !== 'undefined' && typeof a === "number"){
    return a * b
  }
  if (typeof a === "string" && typeof b === "undefined"){
    return a.toUpperCase() 
  }
  throw new Error("Incorrect Params");
}

Function behavior:

  • When only a is present and it is a string, convert it to uppercase.

  • When both a and b are present, both must be numbers, and multiply them.

  • Any other type of combination throws an error


The question is, can it be typed in such a way that this behavior is reflected in the IDE?

That is, when only one parameter is passed to it, the IDE will show this

Function one parameter

But when passed two, or a comma is added, the behavior changes to show this:

Function two parameters

This would allow to avoid error during code development.


Clarification: The exposed function is only an example and not a real use case. Still I think this would be very useful and I have seen it implemented in the Google Apps Script IDE. I would like to know what the internal mechanism is, and if it can be extended to VSCode using only Typescript.


Emel
  • 2,283
  • 1
  • 7
  • 18

2 Answers2

1

You're after function overloading, which in your case would be implemented like so:

function test(a: number, b: number): number;
function test(a: string): string;

function test(...args: any[]): string | number {
  // implementation based on args
}

Which presents like this in your IDE - notice the 1/2 to denote the possible overloads, which you can cycle though:

enter image description here

Marty
  • 39,033
  • 19
  • 93
  • 162
  • Just one question, why I can't write the last overload as: `function test(a: any, b: any): string | number` – Emel Jun 22 '22 at 01:30
  • 1
    @Emel there's no reason you can't, go for it! – Marty Jun 22 '22 at 01:32
  • Get an error in the IDE, for `function test(a: string): string` : `This overload signature is not compatible with its implementation signature.` – Emel Jun 22 '22 at 01:33
  • 1
    @Emel Oh yep it will need to be `function test(a: any, b?: any)` since `b` would be omitted for one of the signatures. – Marty Jun 22 '22 at 01:34
  • Just figure out by myself, thanks @Marty!! Have a nice day! – Emel Jun 22 '22 at 01:35
0

After reviewing the marked as duplicated question a possible solution will be (not the most optimal because I have to change the behavior of the function):

function test(...args: [a: string] | [a: number, b: number]): number | string {
  let a = args[0];
  let b = args[1];
  if (typeof b !== "undefined" && typeof a === "number") {
    return a * b;
  }
  if (typeof a === "string" && typeof b === "undefined") {
    return a.toUpperCase();
  }
  throw new Error("Incorrect Params");
}
Emel
  • 2,283
  • 1
  • 7
  • 18