@babel/plugin-transform-typescript strips vital JSDoc @typedef comments
See original GitHub issueBug Report
EDIT: See my comment https://github.com/babel/babel/issues/9916#issuecomment-489404010 below, there is a strange inconsistency depending on the location of import
statements.
Running Babel with nothing but @babel/plugin-transform-typescript removes all but the very first of many JSDoc @typedef
comments.
Those comments are for (and just above) Typescript type definitions (export type, export interface). When the Typescript types are stripped, so are the JSDoc comments. When I run jsdoc3
to generate the HTML API docs this tool too runs Babel and this plugin in order to be able to parse the file. Obviously, the removal of the JSDoc is counterproductive especially in this use case.
Environment
-
Babel version(s): 7.4.4
-
Node/npm version: 11.14
-
jsdoc 3.5.5
-
OS: Linux
-
How you are using Babel: jsdoc3, config (jsdoc.json, babel section):
"babel": {
"extensions": ["js","ts","jsx","tsx"],
"presets": ["@babel/preset-typescript"],
"plugins": [],
"babelrc": false
},
Example
Here is an excerpt of the beginning of a file with many TS type definitions and there accompanying JSDoc comments.
/**
* This defines the creation status string constants for files
* @global
* @typedef {("new"|"exists")} FileCreationStatus
*/
export type FileCreationStatus = typeof CREATION_STATUS[keyof typeof CREATION_STATUS];
/**
* @global
* @typedef {Object} FileCreation
* @property {SHA256Hash} hash - The SHA-256 hash of the contents of a versioned ONE object
* @property {FileCreationStatus} status - A string constant showing whether the file
* already existed or if it had to be created.
*/
export interface FileCreation {
hash: SHA256Hash;
status: FileCreationStatus;
}
/**
* This defines the creation status string constants for objects.
* @global
* @typedef {FileCreationStatus} ObjectCreationStatus
*/
export type ObjectCreationStatus = FileCreationStatus;
After the transformation only this is left of these comments:
/**
* This defines the creation status string constants for files
* @global
* @typedef {("new"|"exists")} FileCreationStatus
*/
export type FileCreationStatus = typeof CREATION_STATUS[keyof typeof CREATION_STATUS];
Lots and lots of comments erased while there were nothing but Typescript type definitions encountered by the parser. Only when there was actual JS code again did the comment removal stop.
Proposed solution
Don’t delete any JSDoc (or any) comments. Comment removal should be left to the boolean “comment” Babel configuration property and whatever Babel code is following that instruction. If it is not set to true
no comments should be removed, especially not JSDoc @typedef
ones.
Issue Analytics
- State:
- Created 4 years ago
- Comments:8 (2 by maintainers)
@nicolo-ribaudo I found something really weird, the issue is more complicated an nuanced. The comment removal is not always happening! If it was so simple as you show in the parser, the comment belong to the parsed statement so it’s removed, then it would be a reliable outcome, but it isn’t. It seems to be related to
import
statements, at least I can work around it by moving them, see last paragraph below.Here is a Babel Repl example
Try either one of
import
statement does it tooimport
statement below the TS type definitionsWith that import line all comments are gone as reported as my original problem. When that line is not there, all the comments are there all of a sudden!
I now moved all the
import
statements AFTER all the type definitions in all of my files. No comments are removed any more. This could work as a workaround, although to my mind at least it isn’t logical to have imports after exports (since the exports often use imported types) so my sense of order doesn’t like it 😃Besides, I don’t like the randomness of this, the comment removals, I think there should at least be consistent behavior (to a normal human developer, of course, somewhere deep inside the parser’s bowels this is consistent).
UPDATE: I experimented with the plugin code, removing everything (that changes the AST) but
and I still get this
import
statement location dependent behavior. So it isn’t in the plugin but deeper. IMO node removal should not deliver different results based on the location ofimport
statements, that makes no sense to me.Something else I just remembered probably worth mentioning: I recently switched from Flow to TypeScript, mostly just by renaming files *.js => *.ts. I never noticed anything previously, despite having had pretty much the same Babel workflow, only plugin flow-remove-types instead of the TypeScript plugin which also only removes types. This contradicts the previous paragraphs, where I find that cutting down the code in the TS plugin to just two plain removal statements (which surely flow-remove-types has two) makes no difference.
@pauloptimizely Thanks! I prefer the workaround I just found, see above, better than adding semicolons to my subjective feeling (and my IDE would disapprove about that too).
I explain it in the second paragraph: I’m running jsdoc! To generate the HTML API docs! I need exactly the JSDoc! In that case the code itself actually doesn’t matter at all apart from those declarations that jsdoc uses.
There is a top-level babelrc setting for that!! If that is
false
it is not the right behavior to remove comments.