Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Switch default type mode to typescript #834

Closed
brettz9 opened this issue Feb 2, 2022 · 12 comments
Closed

Switch default type mode to typescript #834

brettz9 opened this issue Feb 2, 2022 · 12 comments

Comments

@brettz9
Copy link
Collaborator

brettz9 commented Feb 2, 2022

This might await some jsdoc-type-pratt-parser changes (@simonseyock ), but I'd like to move toward enabling typescript mode by default.

This change is not proposed out of a desire to move to TypeScript source code (I personally like to avoid it, tbh), but due to the fact that even for plain JSDoc + JS usage, the tooling system of the TypeScript flavor of JSDoc is by far more robust and well-maintained than is plain JSDoc.

One can continue to use JSDoc + vanilla JavaScript in this "typescript" mode, e.g., via TypeScript's tsc --allowJs (and avoid needing JavaScript refactoring by not using --checkJs); this proposal is just to change the flavor of JSDoc to the TypeScript flavor, not to require TypeScript-specific superset-of-JavaScript syntax.

Although:

  1. There are some unsupported patterns/types and tags from the original JSDoc
  2. Typedef inheritance as originally specified doesn't work currently in TypeScript, forcing one to potentially work with TypeScript declaration files if the intersection operator doesn't suffice...

...one can still get by using JavaScript and JSDoc alone, and with a JSDoc type flavor which mostly just expands on JSDoc. Also, "unsupported" tags, etc., may just mean not having them achieve the intended type checking effect; they still may be silently ignored within a document if you still want to have them there.

Morever, the TypeScript flavor of JSDoc offers these additional advantages:

  1. Active development and attempts at higher specification
  2. Well-maintained tooling for documentation and type-checking
  3. Specification of 3rd party imports!!!
  4. Greater expressiveness in types
  5. Convenient shorthands

And of course, TypeScript fans should appreciate it for their plain JS projects (they already get typescript mode on by default when using @typescript-eslint/parser).

Although TypeScript can get rather intricate with certain features, again, it is not difficult to get going on basic projects. I recommend a tutorial like https://gils-blog.tayar.org/posts/jsdoc-typings-all-the-benefits-none-of-the-drawbacks/ as the official docs, while pretty good considering, might not be perfectly inviting to newcomers. Besides getting docs, you can get type checking on your plain JavaScript, and the ability to export your types.

(The community might benefit from a wiki of tips, e.g., the need to use parentheses with inline type conversions /** @type {{ a: string, b: number }} */ (someExpression); to which we could link.)

Feedback or questions on the proposal welcome.

Update: We are also rolling up #800 to ensure that check-types formalizes the preferences for object and Object<> and does so for even jsdoc mode.


Want to back this issue? Post a bounty on it! We accept bounties via Bountysource.

@thernstig
Copy link

I support this 😄 We started using typescsript mode and converted all our JSDoc to use TypeScript where possible and it helped immensely. Especially with editors such as VS Code supporting it and giving us type checking in our JavaScript project, which is a fairly large project.

The great, great benefit of using this is more expressiveness in the types functions take. We started using https://www.npmjs.com/package/tsc-silent to even lint it in CI. It thus gives us free type checking in our huge JavaScript project. In addition, starting to use this for JSDoc first makes the transitition to pure TypeScript much easier for projects in the future, if they so wish. Because:

  1. It is a good way for users to learn TypeScript types, without going full TypeScript
  2. Most code will already be properly typed, especially with the help of linting in CI via e.g. tsc-silent.

@briandipalma
Copy link

FWIW I'm an other user who also support this. Again another large JS codebase where TS JSDoc is being used to help tame it a bit.

@brettz9
Copy link
Collaborator Author

brettz9 commented Mar 25, 2022

I am not sure that things are quite ready yet to promote TypeScript for plain JavaScript users, as I've found a couple pretty significant obstacles to using plain JavaScript in TypeScript mode (at least if one is to get a decent resulting declaration file):

  1. @typedef will export types whether you want them exported to 3rd parties or not, though this is not as problematic as...
  2. If you need to specify you are exporting a class of a given type, but that class isn't global, you can't really do so (at least without creating a dummy global class).

Although some may say something is better than nothing, especially since plain JSDoc doesn't support declaration file generation at all, but these issues came up pretty quickly in projects I attempted to work with, and I think these ought to be resolved on the TS side before we can confidently say the JavaScript-only approach is ripe for promotion on our end as the default.

WDYT?

@briandipalma
Copy link

I've never used the declaration file functionality with our JS code base. I'm not really sure what to say to your points, they've not been problems for us. If I want a type I import it from the module that defines it. I don't care if all the types are exported even if some are for internal use only.

@briandipalma
Copy link

Could you explain exactly what you are doing that's causing these issues to be problems?

@brettz9
Copy link
Collaborator Author

brettz9 commented Mar 26, 2022

I've never used the declaration file functionality with our JS code base. I'm not really sure what to say to your points, they've not been problems for us.

I realize causing a declaration file is not going to be a problem for everyone, and yes, regular JSDoc doesn't even let you prepare the equivalent of a declaration file.

However, my feeling is that plain JavaScript ought to be a first class citizen in this ecosystem, including for purposes of publishing. One wouldn't want to see, for example, JavaScript support being touted and then find that in order to get the benefits for publishing, one needed to switch to full-blown TypeScript.

Or worse, once users got used to the degree of support that existed for plain JavaScript, the tools later abandoned the support that existed. Kind of an embrace, extend, and extinguish scenario. TypeScript may be open source, but its complexity doesn't mean anyone is capable of taking it over.

If I want a type I import it from the module that defines it. I don't care if all the types are exported even if some are for internal use only.

This first problem I described, yes, is not as serious, but given how frequently one needs to use local typedefs, especially if one wishes to make one's code more readable using shorter syntax, it might invite problems for publishers if others come to use and depend on those types, and in any case, doesn't allow one to advertise the clean public API, and only this API, that one will continue to support without breaking changes. If a project drops internal use of one type, some might consider this a breaking change, whereas the project might have never intended the type to be exported in the first place.

But again, this is not quite as serious as the second problem I listed whereby one cannot just use JSDoc to define an exportable class interface which external projects do need.

Could you explain exactly what you are doing that's causing these issues to be problems?

My first attempt was on allowing ESLint's espree parser to have its declaration files auto-generated based on plain JavaScript+JSDoc. My changes--which also called for significant refactoring--are at eslint/espree@main...brettz9:tsc-acorn2 (note also the commit messages, "INCOMPLETE" items). Notice the dummy class in lib/espree.js that I had to create and export in order to get a class type that could be used in the other files which required awareness of the type.

This was not some vastly complex project; the first file I started converting turned up the above-mentioned problems.

And I ran into the local typedef problem for another project as well.

But again, I recognize that only the second issue is a problem for those just wishing to consume, and some could work around this too. But for plain JavaScript usage to be deemed a mature solution, it shouldn't require many code changes in the first place, and what it does require should at least be basically as robust as regular TypeScript, at least for the more common publishing use cases.

@briandipalma
Copy link

OK, I see your issues. Although I still feel like I'm missing something. Isn't the only way to create declaration files is to use TS JSDoc? So I don't see how making typescript mode the default changes anything around the issues you mention. If someone wants declaration files they have to live with the shortcomings if they don't then they aren't affected by these issues?

@brettz9
Copy link
Collaborator Author

brettz9 commented Mar 29, 2022

Yes, you are right, but see the first block of my reply in my previous comment. One aspect I didn't mention there is that it comes at some cost, not only to change the JSDoc syntax, but also actually calls for refactoring of files. That might only apply for checkJs (which again is a benefit that generally doesn't apply for old JSDoc, unless using something like tern.js perhaps), but for me, blessing TypeScript is kind of a symbolic act for me to say "It's pretty much all ready for you now.", and I'm kind of hoping this might prompt some pressure on the TypeScript community to fix these two issues.

@briandipalma
Copy link

Surely if someone wanted to keep the old JSDoc standard they could just change their config? I guess there's no urgency to move to TS mode as it's a small piece of config to enable it.

@jimmywarting
Copy link

@brettz9
Copy link
Collaborator Author

brettz9 commented Jul 4, 2022

You might not need TypeScript... (syntax)

Thanks for the reference, but although that article speaks about the "TypeScript flavor syntax", I think it is speaking more about TypeScript's own syntax, rather than disfavoring use of the TypeScript flavor within JSDoc. In fact, in the article, e.g., within the "Generics in JSDoc" section, its example uses the TypeScript-specific flavor of JSDoc within JSDoc comments. So I think if anything this article is speaking in favor of switching to the TypeScript flavor of JSDoc (just not to the TypeScript language).

brettz9 added a commit to brettz9/eslint-plugin-jsdoc that referenced this issue May 7, 2023
BREAKING CHANGE:

Users must now opt into adding `settings.jsdoc.mode` set to `"jsdoc"` if they want
normal JSDoc mode. Note that "typescript" mode does not need to imply use of TypeScript
syntax, but rather use of the TypeScript flavor within JSDoc comment blocks which holds
the advantages of working in IDEs to draw in third-party module documentation and optionally
allowing one to type check one's JavaScript code by TypeScript. There
are also tools for building docs with this flavor (e.g., typedoc).
@brettz9 brettz9 closed this as completed in 055adf8 May 7, 2023
@github-actions
Copy link

github-actions bot commented May 7, 2023

🎉 This issue has been resolved in version 44.0.0 🎉

The release is available on:

Your semantic-release bot 📦🚀

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

4 participants