microsoft / microsoft/TypeScript
`checkJs` skips `.mjs`/`.cjs` beside a `.d.mts`/`.d.cts`, but not `.js` beside a `.d.ts`
Chưa có ai nhận issue này.
- Ngôn ngữ chính
- Go
- Star
- 111k
- Fork
- 14.3k
- Merge trung bình
- 2 ngày 4 giờ
- Pull request đã merge (30 ngày)
- 132
Mô tả
### 🔎 Search Terms
checkJs, allowJs, .d.mts, .d.cts, declaration file adjacent to implementation, file silently dropped from program, extension priority
### 🕗 Version & Regression Information
Reproduces identically on 5.9.3, 6.0.3, and 7.1.0-dev.20260916.1. Long-standing, not a regression.
### ⏯ Playground Link
Not applicable: needs two sibling files on disk plus `moduleResolution: nodenext`.
### 💻 Code
Three directories, identical but for extensions. Same `tsconfig.json` in each; `package.json` has `"type": "module"` only for the `.mjs` case.
`index.js` / `index.mjs` / `index.cjs`:
```js
export const n = 1;
const bad = null;
bad.a.b.c();
```
`index.d.ts` / `index.d.mts` / `index.d.cts`:
```ts
export declare const n: number;
```
```json
{
"compilerOptions": {
"target": "esnext",
"module": "nodenext",
"moduleResolution": "nodenext",
"allowJs": true,
"checkJs": true,
"strict": true,
"noEmit": true
}
}
```
### 🙁 Actual behavior
```
index.js + index.d.ts -> error TS18047: 'bad' is possibly 'null'.
index.mjs + index.d.mts -> (no output)
index.cjs + index.d.cts -> (no output)
```
The same authoring relationship — a hand-written declaration file beside its implementation — produces opposite outcomes based only on the file extension.
In the `.mjs`/`.cjs` cases the implementation is not merely unchecked, it is absent from the program: `--listFiles` reports only `index.d.mts`. In the `.js` case `--listFiles` reports both `index.d.ts` and `index.js`.
### 🙂 Expected behavior
The three rows should agree. Either all of them check the implementation, or none do.
I'd expect the `.js` row to be the correct one — the declaration file describes the module for consumers, and `checkJs` still checks the implementation — but consistency matters more than which way it goes.
### Additional information
#47796 reported the `.mjs`/`.mts` variant and was closed as "Working as Intended", on the rationale that the JS file is a build artifact of the TS file, and that "the compiler only automatically pulls in one copy of a file with the same basename (the most TS-y one)".
That rationale doesn't extend to this case:
- A `.d.mts` is not something a `.mjs` is emitted *from*, so the build-artifact framing doesn't apply. `.d.ts` + `.js` is the same relationship, and there the compiler does pull in both.
- Neither does the one-copy-per-basename rule, for the same reason — `index.js` and `index.d.ts` are both in the program.
The failure is silent, which is what makes it expensive: a package shipping `.mjs`/`.cjs` with adjacent hand-written declarations gets no checking of its implementation at all, while every sibling module without a declaration file is checked normally. `tsc` exits 0 and CI is green. I found this only by deliberately breaking a file and noticing the build still passed. Per #47796, VS Code *does* report these errors, so the editor and CI silently disagree.
#64098 is the same silent-drop shape from wildcard `include` (`hasFileWithHigherPriorityExtension`), if the two are related.
So, concretely:
1. Make the three rows consistent, or
2. if this is intended, document which sibling extensions suppress checking, and emit a diagnostic when an input file is dropped from the program for this reason.
Hướng dẫn đóng góp
Bắt đầu từ đâu
- Đọc hết issue, rồi đọc hướng dẫn đóng góp của dự án.
- Bình luận trên issue rằng bạn sẽ nhận — tránh hai người làm cùng một việc.
- Fork repository và làm thay đổi trên một nhánh.
- Mở pull request có tham chiếu số hiệu của issue.
Hướng nghiên cứu
Bắt đầu bằng cách chạy quy trình tái hiện trong ba thư mục với tsc --listFiles và so sánh kết quả .js/.d.ts, .mjs/.d.mts và .cjs/.d.cts. Truy vết hành vi ưu tiên phần mở rộng xung quanh hasFileWithHigherPriorityExtension, được tham chiếu từ #64098. Được xem là hoàn tất khi cả ba trường hợp hoạt động nhất quán và có độ bao phủ cho kịch bản bị loại bỏ im lặng.
Do mô hình lập chỉ mục viết ra từ nội dung của issue.
Đánh giá
- Công nghệ
- javascript, typescript
- Lĩnh vực
- compilers
- Loại issue
- Lỗi
- Độ khó
- 4/5
- Thời gian dự kiến
- 3-5 ngày
- Mức độ hoạt động
- Sôi nổi
- Độ rõ ràng
- Khá rõ ràng
- Mức phù hợp với người mới
- 52/100