Skip to content

JSDoc @template tag silently terminates @overload tag signature parsing #52844

@SamB

Description

@SamB

Bug Report

🔎 Search Terms

Um, aside from the words in the subject line, I guess "confusing"?

🕗 Version & Regression Information

Seen in 5.0.0-beta and 5.0.0-dev.20230217

  • I was unable to test this on prior versions because @overload is new in 5.0.0

💻 Code

// @checkJs: true
// @strict: true
// @outDir: dist/
// @declaration: true
// @filename: jsFileFunctionOverloads.js

/**
 * @template T
 * @param {T} x 
 * @returns {T}
 */
const identity = x => x;

/**
 * @overload
 * @template T
 * @template U
 * @param {T[]} array 
 * @param {(x: T) => U[]} iterable 
 * @returns {U[]}
 */
/**
 * @overload
 * @template T
 * @param {T[][]} array
 * @returns {T[]}
 */
/**
 * @param {unknown[]} array 
 * @param {(x: unknown) => unknown} iterable 
 * @returns {unknown[]}
 */
function flatMap(array, iterable = identity) {
  /** @type {unknown[]} */
  const result = [];
  for (let i = 0; i < array.length; i += 1) {
    result.push(.../** @type {unknown[]} */(iterable(array[i])));
  }
  return result;
}

⏯ Playground Link

Workbench Repro

AST Viewer link (Unfortunately, I couldn't figure out how to set the options in the link; set Version to "@next (5.0.0-dev-[...])" and Script Kind to "ts.ScriptKind.JS".)

🙁 Actual behavior

When the @overload is written before a @template tag, the overload signature ends at the @template tag, and the only sign that this has happened is the error message "This overload implicitly returns the type 'any' because it lacks a return type annotation." highlighting only the word "overload" (with no indication of where signature parsing stopped), and even that only happens in strict mode (not sure which exact flag).

(Unfortunately, the bug workbench won't actually show you the proper error highlights, and I found it too difficult to manage the settings in the standard Playground. I mean ... dozens of checkboxes??? Huh?)

P.S.

I've noticed that there's nowhere to hover that shows you TypeScript's understanding of the overload signatures; hovering the function's name only shows you function flatMap(array: any, iterable?: (x: any) => any): any[] (+2 overloads). Stranger yet, // ^? shows that on the editor but when you look at the "Asserts" tab it says "function flatMap<T, U>(): any (+1 overload)". (Fiddling around locally indicates that hovering in vscode would also give just (+1 overload).)

Conclusion: the workbench's editor is feeding the twoslash document straight to TypeScript along with the individual files ... and, when processed as TypeScript, the JSDoc @overloads are ignored and the function is given the implementation type as its declared type, but the other output Workbench shows is from an entirely distinct instance of TypeScript.

🙂 Expected behavior

I would expect this to either work, or give clear diagnostics saying that you have to put @template before @overload, because it's not at all obvious that this would be required; it's not like there's an analogous overload keyword in TypeScript that comes after the type parameter list but before the ordinary parameter list or something. (I ... actually just checked to make sure that's true, because sometimes I have a terrible memory.)

Metadata

Metadata

Assignees

Labels

Fix AvailableA PR has been opened for this issueNeeds InvestigationThis issue needs a team member to investigate its status.

Type

No type

Projects

No projects

Relationships

None yet

Development

No branches or pull requests

Issue actions