Skip to content

[Design Policy] Consider JSDoc feature parity with Typescript #30624

Description

Search Terms

jsdoc parity, jsdoc equivalence, jsdoc

Suggestion

The JSDoc mode of TypeScript is very useful in cases where a build step (esp for node libraries for example) isn't desired or when other constraints prevent not writing in JS. However it can be annoying when trying to implement something that can't be expressed in JSDoc mode due to requiring Typescript syntax.

As such I would like to propose that TypeScript ensures that anything that can be written inside a .ts file can be expressed (in at least some way) within a pure javascript + jsdoc file.

In order to get an idea of the current scope needed for feature parity this is a list of issues and features that break parity between the two modes (if any are missing just say and I'll add to the list):

  • [Bug?] No way to express the object type
    • Currently in JSDoc /** @type {object} */ is equivalent to /** @type {any} */, there doesn't seem to be any way to represent const x: object purely in JS + JSDoc, this seems like a bug. Fixed
  • interface
  • abstract class
  • protected/private members Fixed
  • function overloading v5.0
  • defaults for generics
  • declare syntax in it's various forms and declaration merging
    • declare global { ... }
    • declare module "moduleName"
    • declare class Foo
    • declare interface
    • declare namespace
  • namespace
  • enum
    • /** enum */ is not quite equivalent
  • as const v4.5
  • non-null assertion expr!

Checklist

My suggestion meets these guidelines:

  • [✓] This wouldn't be a breaking change in existing TypeScript/JavaScript code
  • [✓] This wouldn't change the runtime behavior of existing JavaScript code
  • [✓] This could be implemented without emitting different JS based on the types of the expressions
  • [✓] This isn't a runtime feature (e.g. library functionality, non-ECMAScript syntax with JavaScript output, etc.)
  • [✓] This feature would agree with the rest of TypeScript's Design Goals.

Activity

  1. AlCalzone commented on Mar 28, 2019

    @AlCalzone
    Contributor
  2. ExE-Boss commented on Apr 4, 2019

    @ExE-Boss
    Contributor

    Function overloading can be done using:

    /** @type {((name: string) => Buffer) & ((name: string, encoding: string) => string))} */
    const readFile = (name, encoding = null) => { … }

    I discovered this purely by accident.

  3. texastoland commented on Apr 18, 2019

    @texastoland
    Contributor
    • as const

    #30445

  4. steinuil commented on Apr 18, 2019

    @steinuil

    .d.ts files can contain many of these declarations without breaking JS builds, since they don't have to be imported.

  5. AlCalzone commented on Apr 18, 2019

    @AlCalzone
    Contributor

    But they don't work for the current file, only imported ones.

  6. steinuil commented on Apr 18, 2019

    @steinuil

    But they do!

    // test.d.ts
    interface X { a: string }
    
    // test.js
    /** @type {X} */
    const x = { a: 'one' };

    You just have to include the .d.ts files in your tsconfig.json.

    By the way, many of these tricks I also discovered by pure accident; it would be nice if they were properly documented. The page dedicated to this has improved a lot recently, but there's still a lot of things I had to figure out by trial-and-error.

  7. AlCalzone commented on Apr 18, 2019

    @AlCalzone
    Contributor

    steen (@steinuil) Ok I should be more specific then. Function overloading does not work - at least the last time I checked:

    // test.d.ts
    declare function test(arg1: string, arg2: number, arg3: () => void): void;
    declare function test(arg2: number, arg3: () => void): void;
    declare function test(arg1: string, arg3: () => void): void;
    declare function test(arg3: () => void): void;
    
    // test.js
    function test(arg1, arg2, arg3) {
      // ... args are `any`
    }
  8. texastoland commented on Apr 18, 2019

    @texastoland
    Contributor

    Also nonNull! #23405.

  9. weswigham commented on Apr 18, 2019

    @weswigham
    Member

    AlCalzone function overloads only affect usages of the function, not parameter types within a function - this is true in TS, too. You need to actually annotate parameter types on the implementation (compatible with the overloads) to get checking in the function body.

  10. ExE-Boss commented on Apr 18, 2019

    @ExE-Boss
    Contributor

    Also, in function overloads, it’d be great if the implicit arg types were unknown instead of any, but that depends on #27265 (and #30813).

  11. jonnytest1 commented on Jun 22, 2019

    @jonnytest1

    Anderson Goulart (@global) doesnt seem to work
    image

    having them in the same file yields he same result

    { the error is cannot find name 'foo' }

  12. thw0rted commented on Nov 27, 2019

    @thw0rted

    Would e.g. #28730 fall under this umbrella? I'm trying to use JSDoc to describe existing sources that define getter/setter properties with Object.defineProperties and the only way I've found to do so is with @memberof. (For an example, see my comment on that issue.)

  13. bennypowers commented on Jan 27, 2020

    @bennypowers

    I'm using this hack to get support for the @private JSDoc tag currently. Would love to see this land in TS.

    const REGEXP = /@private(?<suffix>[\n\r\s\w]+)\*\/(?<whitespace>[\n\r\s]+)(?<memberName>[\w]+)\b/g;
    
    const source = `
    export class Foo {
      /** Focuses the element. */
      focus(): void;
      /**
       * @param  {string} message
       * @return {Error}
       * @private
       */
      createError(message: string): Error;
    }
    `
    
    source.replace(REGEXP, (...args) => {
      const [{suffix, whitespace, memberName}] = [...args].reverse();
      return `@private${suffix}*/${whitespace}private ${memberName}`
    })
  14. trusktr commented on Feb 27, 2024

    @trusktr
    Contributor

    Here's an issue for declaration merging with JSDoc:

  15. added
    SuggestionAn idea for TypeScript
    Awaiting More FeedbackThis means we'd like to hear from more people who would be helped by this feature
    and removed
    Meta-IssueAn issue about the team, or the direction of TypeScript
    on Oct 23, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Awaiting More FeedbackThis means we'd like to hear from more people who would be helped by this featureSuggestionAn idea for TypeScript

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions