question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Return type annotations ignored with recursive closures using JSDoc

See original GitHub issue

TypeScript Version: 3.5.1

Search Terms:

  • “implicit any type”
  • “circular reference”
  • “jsdoc”
  • “recursive”
  • “closure”

Code

I have a fairly complex use case in a project which uses vanilla JS with type annotations in JSDoc comments. The long and the short is that there is a function which returns a function, which may recursively call itself and will reassign some closure variables.

Here is a silly example which gets the point across and demonstrates the same issue:

/**
 * @returns {function(): number}
 */
function circular() {
  let rand = Math.random();

  return /** @type {function(): number} */ (function tryAgain() {
    if (rand < 0.5) {
      return rand;
    }

    rand = Math.random();
    return tryAgain();
  });
}

Expected behavior:

TypeScript should know that the return type of tryAgain is a number.

Actual behavior:

When run with:

tsc --allowJs --checkJs --noEmit --strict --target ES2017 *.js

The following error is thrown:

error TS7023: 'tryAgain' implicitly has return type 'any' because it does not have a return type annotation and is referenced directly or indirectly in one of its return expressions.

At the very least, this error seems pretty erroneous. The tryAgain function has two return type annotations (I have tried both styles in an attempt to fix this). The larger issue is that I need some way to get TypeScript to compile this code without a massive refactor.

Playground Link:

None (code is JavaScript).

Related Issues:

This has a circular reference similar to #26623. However for that issue the solution was to add an explicit return type annotation. In my case (perhaps because I am using JSDoc), TypeScript seems to be ignoring all explicit annotations.

Issue Analytics

  • State:open
  • Created 4 years ago
  • Reactions:2
  • Comments:5

github_iconTop GitHub Comments

1reaction
boazblakecommented, Jun 19, 2020

@delventhalz Thank you 👍🏼

1reaction
delventhalzcommented, Jun 9, 2020

@boazblake You introduced a bug into the link you posted. You added a line break after the return statement:

  return /** @returns {number} */
   function tryAgain() {
    if (rand < 0.5) {

You cannot have a return statement on its own line. Automatic Semicolon Insertion will insert a semicolon directly after the return, causing you to return undefined. You can plainly see this if you look at the generated code in the right column:

    return; /** @returns {number} */
    function tryAgain() {
        if (rand < 0.5) {

To fix your issue, delete the extraneous line break. The workaround then works as advertised:

  return /** @returns {number} */ function tryAgain() {
    if (rand < 0.5) {
Read more comments on GitHub >

github_iconTop Results From Across the Web

How to write an explicit return type annotation for a recursive ...
"...and checks types using tsc with type annotations written in JSDoc comments..." Well that's...really flippin' cool. I didn't know tsc ...
Read more >
Configuring JSDoc with a configuration file
How to configure JSDoc using a configuration file. ... Configuring plugins; Specifying recursion depth; Specifying input files; Specifying the source type ...
Read more >
JSDoc Reference - TypeScript: Documentation
JSDoc Reference. The list below outlines which constructs are currently supported when using JSDoc annotations to provide type information in JavaScript files.
Read more >
Google JavaScript Style Guide
To reference the Closure goog namespace, import Closure's goog.js . ... Dependency} param All external types used in JSDoc * annotations must be ......
Read more >
Jsdoc export typedef - Caritas Castellaneta
One way to think about TypeScript is as a thin layer around JavaScript that adds type annotations. Separated export is not shown in...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found