microsoft / microsoft/TypeScript
Type literals in declaration files are emitted with comment blocks from the wrong source file
@rbuckton is already working on this.
Since Apr 10, 2024.
- Dominant language
- Go
- Stars
- 111k
- Forks
- 14.4k
- Avg merge
- 1d 19h
- Merged PRs (30d)
- 117
Description
🔎 Search Terms
"comments", "comment emit", "declaration comments", "inconsistent comments", ".d.ts comment", ".d.ts jsdoc", "wrong file", "crlf"
🕗 Version & Regression Information
- This is the behavior in every version I tried, and I reviewed the FAQ for entries about comments
⏯ Playground Link
💻 Code
// @declaration: true
// @showEmit
// @showEmittedFile: bar.d.ts
// @filename: foo.ts
// OFFSET.............................
export const obj = {
/** Comment for `prop` */
prop: "",
};
// @filename: bar.ts
import { obj } from "./foo";
export const x = {
A: obj,
/** Comment for `B` */
B: obj,
C: obj,
};
🙁 Actual behavior
The emitted bar.d.ts declaration file includes the comment on line 17 (preceding the B property assignment in bar.ts) above each prop signature:
export declare const x: {
A: {
/** Comment for `B` */
prop: string;
};
/** Comment for `B` */
B: {
/** Comment for `B` */
prop: string;
};
C: {
/** Comment for `B` */
prop: string;
};
};
Note that the OFFSET... comment on line 5 (in its entirety) is necessary to reproduce this behavior. This just so happens to align the start of the comment range for the prop assignment in foo.ts (63) one character past the start of the B assignment's comment range in bar.ts (62).
Strangely, if I remove a single character from line 5 (so that both comment range starts are perfectly aligned), the comment above B.prop is omitted, but the others remain:
export declare const x: {
A: {
/** Comment for `B` */
prop: string;
};
/** Comment for `B` */
B: {
prop: string;
};
C: {
/** Comment for `B` */
prop: string;
};
};
Any other changes to the number of characters preceding the object literal expression in foo.ts results in the expected bar.d.ts:
export declare const x: {
A: {
prop: string;
};
/** Comment for `B` */
B: {
prop: string;
};
C: {
prop: string;
};
};
🙂 Expected behavior
Ideally, the emitted bar.d.ts declaration file should include the correct comments for all property signatures:
export declare const x: {
A: {
/** Comment for `prop` */
prop: string;
};
/** Comment for `B` */
B: {
/** Comment for `prop` */
prop: string;
};
C: {
/** Comment for `prop` */
prop: string;
};
};
But I understand from the FAQ that might have a performance impact. In that case, I would expect the bar.d.ts file to consistently omit comments for type literals defined outside bar.ts:
export declare const x: {
A: {
prop: string;
};
/** Comment for `B` */
B: {
prop: string;
};
C: {
prop: string;
};
};
In other words, the compiler should handle this corner case where comment positions just happen to align across multiple files. The current behavior can lead to weird declaration file inconsistencies across platforms (due to CR characters potentially aligning/mis-aligning comment ranges on Windows only).
Additional information about the issue
A couple other observations:
- This is only reproducible with a JSDoc-style comment block (
/**) inbar.ts - Changing or removing the comment for
propon line 7 has no effect on the emittedbar.d.ts - This appears to happen anytime a type defined in
foo.tsis substituted for an expression inbar.ts(and comment ranges align). For example, here's another repro showing similar behavior whenbar.tsincludes calls to a function (returning an object literal) defined infoo.ts, and yet another where said function returns a class expression instead.
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Assessment
This issue has not been assessed yet.