You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
{{ message }}
Repository navigation
In JS, jsdoc should be able to declare functions as overloaded #25590
You can specify overloads in Typescript by providing multiple signatures. You should be able to do the same thing in Javascript. The simplest way I can think of is to allow a type annotation on a function declaration.
Examples
/** @typedef {{(s: string): 0 | 1; (b: boolean): 2 | 3 }} Gioconda *//** @type {Gioconda} */functionmonaLisa(sb){// neither overloads' return types are assignable to 1 | 2, so two errors should be loggedreturntypeofsb==='string' ? 1 : 2;}/** @type {2 | 3} - call should resolve to (b: boolean) => 2 | 3, and not error */vartwothree=monaLisa(false);// js special property assignment should still be allowedmonaLisa.overdrive=true;
Note that checking parameters against the implementation parameters will be trivial since there's no obvious type but any for the implementation parameters. Checking of return types against the implementation return type will have to use the return type of the function body as the implementation return type. That check will also likely be trivial since function-body return types usually depend on parameters.
How would one provide comments and parameter descriptions (/** @param */) when doing this?
Sometimes it is necessary to highlight the differences between overloads. In .d.ts files this works by annotating each single overload with its own comment. See also #407
Too bad this seems pretty low on your priorities :( I just ran into an issue where it is impossible to document a method signature in JavaScript due to this. I have a function where all arguments except the last one are optional:
Here's a type that is too permissive, but it's pretty close: declare function test(arg123: string | number | () => void, arg23?: number | () => void, arg3?: () => void): void
In order to express dependencies between types without overloads, you need conditional types:
declare function test<T extends string | number | () => void>(
arg123: T,
arg23?: T extends string ? number :
T extends number ? () => void :
never,
arg3?: T extends string ? () => void : never): void
But conditional type syntax doesn't work in JS so you'd have to write a series of type aliases in a .d.ts and reference them.
/** * @type {{ * (s:string) => 1; * (b:boolean) => 2; * }} */constmonaLisa=(sb)=>{returntypeofsb==='string' ? 1 : 2;}lettwo=monaLisa(false);// vscode can recognize that this is 2letone=monaLisa("m");// this is 1
You can not use function monaLisa() to declare it. I think this is a defect.
In class, you can:
The cleanest way to do this that I've found so far is using the Parameters type.
This allows you to declare functions like you usually do, like function functionName() {}, rather than var functionName = function() {}.
And on classes you can declare methods like normally rather than this.methodName = () => {}
/** * This function takes a number and a string. * @callback signatureA * @param {number} num * @param {string} str *//** * This function takes a boolean and an object * @callback signatureB * @param {boolean} bool * @param {Object} obj *//** * @param {Parameters<signatureA> | Parameters<signatureB>} args */functionoverloaded(...args){}
I recently tried to type the following templated overload with JSDoc, without success. Resorted to a .d.ts declaration and @type the export.
I have been forced to do the same. It seems that each typescript/tsserver update becomes stricter. Workaround which used to work, are no longer accepted.
Where possible I just use typescript natively now.
With a workaround it's still possible to do this with jsdoc only, but now we need to use type casting.
And with type casting it now automatically recognizes the types of the parameters:
I have came across the following (a little bit hacky) idea:
/** * @param {number} x * @returns {'number'} */functiontypeName__1(x){};/** * @param {string} x * @returns {'string'} */functiontypeName__2(x){};/** * @param {unknown} x * @returns {string} */functiontypeName(x){returntypeofx;}
Now if we modify the parser slightly and we teach it to interpret [name]__[number] as a body-less function declaration, it seems to work quite nicely. It only requires a couple lines of code to be changed in parseFunctionDeclaration(), i.e. something along these lines:
Of course this is not backwards compatible, so perhaps we could also decorate that declaration with additional JSDoc tag to control this behavior in a more granular way, e.g.
From TS perspective symbols for typeName__1 and typeName__2 are not really declared so if someone tries to use them, e.g. typeName__1(123), this will actually produce an error, which is desirable.
From JS perspective these are just no-op functions which can be safely ignored.
The same technique should work for method declarations.
Activity
AlCalzone commentedon Aug 17, 2018
How would one provide comments and parameter descriptions (
/** @param */) when doing this?Sometimes it is necessary to highlight the differences between overloads. In .d.ts files this works by annotating each single overload with its own comment. See also #407
AlCalzone commentedon Aug 17, 2018
One way I could think of is
but this way, we get an error on the type annotation that the signatures don't match.
AlCalzone commentedon Nov 23, 2018
Too bad this seems pretty low on your priorities :( I just ran into an issue where it is impossible to document a method signature in JavaScript due to this. I have a function where all arguments except the last one are optional:
I'd be really glad if documenting this via JSDoc would be possible in the near future.
sandersn commentedon Nov 26, 2018
Here's a type that is too permissive, but it's pretty close:
declare function test(arg123: string | number | () => void, arg23?: number | () => void, arg3?: () => void): voidIn order to express dependencies between types without overloads, you need conditional types:
But conditional type syntax doesn't work in JS so you'd have to write a series of type aliases in a .d.ts and reference them.
36 remaining items
andiby commentedon Mar 4, 2021
As a workaround these declarations for overloads already work for a long time:
Playground Link
ahocevar commentedon Jun 23, 2021
Unfortunately, the workarounds described here no longer work due to #44693.
RyuGuo commentedon Sep 21, 2021
You can try this:
You can not use
function monaLisa()to declare it. I think this is a defect.In class, you can:
But,
A.funcis a property, not a method in vscode.jespertheend commentedon Sep 30, 2021
I'm doing
(string, callback) => {}type overloading like this:jespertheend commentedon Oct 13, 2021
The cleanest way to do this that I've found so far is using the
Parameterstype.This allows you to declare functions like you usually do, like
function functionName() {}, rather thanvar functionName = function() {}.And on classes you can declare methods like normally rather than
this.methodName = () => {}playground link
Unfortunately the function description doesn't get copied, but hopefully #46353 fixes that.
mhofman commentedon Nov 15, 2021
I recently tried to type the following templated overload with JSDoc, without success. Resorted to a
.d.tsdeclaration and@typethe export.systemmonkey42 commentedon Nov 15, 2021
I have been forced to do the same. It seems that each typescript/tsserver update becomes stricter. Workaround which used to work, are no longer accepted.
Where possible I just use typescript natively now.
andiby commentedon Nov 15, 2021
With a workaround it's still possible to do this with jsdoc only, but now we need to use type casting.
And with type casting it now automatically recognizes the types of the parameters:
Playground Link
mhofman commentedon Nov 15, 2021
TIL you can write a function typedef this way in TS JSdoc! The type cast of the function was expected and I don't mind it in this case.
systemmonkey42 commentedon Nov 15, 2021
Ouch! My brain.
Is there a reference which explains this syntax?
I found https://austingil.com/typescript-function-overloads-with-jsdoc/ which talk about it, but nothing that explains it, especially how the template works in this context.
andiby commentedon Nov 16, 2021
Inside the {...} in jsdoc we can use any TypeScript syntax. And in TypeScript this overload with a generic would look like this:
Playground Link
Now just place your mouse over "asType" and you get the tooltip:
apendua commentedon May 5, 2022
I have came across the following (a little bit hacky) idea:
Now if we modify the parser slightly and we teach it to interpret
[name]__[number]as a body-less function declaration, it seems to work quite nicely. It only requires a couple lines of code to be changed inparseFunctionDeclaration(), i.e. something along these lines:I tested it locally and it works quite well.
Of course this is not backwards compatible, so perhaps we could also decorate that declaration with additional JSDoc tag to control this behavior in a more granular way, e.g.
This approach has a couple of nice properties:
typeName__1andtypeName__2are not really declared so if someone tries to use them, e.g.typeName__1(123), this will actually produce an error, which is desirable.Cow258 commentedon Jan 13, 2024
Successful overload by following this issue
#55056