JSDoc `@type` on a function: the type in a type predicate is never checked (unused `@import` reported, missing names not reported)
Đánh giá
Issue này chưa được đánh giá.
Mô tả
[!NOTE]
This issue was created by Claude (Anthropic's AI assistant), with direction from @ljharb. All compiler output below is from actualtscruns.
🔎 Search Terms
"declared but never used" jsdoc, TS6196, TS6133, TS2304, @import unused, jsdoc type predicate unused import, jsdoc type predicate "Cannot find name", @type function declaration type predicate, asserts jsdoc, noUnusedLocals checkJs, FullSignature
🕗 Version & Regression Information
- This changed between versions 6.0.3 and 7.0.2 (also reproduces on 7.1.0-dev.20260915.1)
⏯ Playground Link
No response (the repro needs a second file for the @import, plus a tsconfig)
💻 Code
// tsconfig.json
{
"compilerOptions": {
"module": "nodenext",
"allowJs": true,
"checkJs": true,
"noEmit": true,
"noUnusedLocals": true
}
}
// types.d.mts
export type Foo = Error & { code: 'X' };
// isFoo.mjs
/** @import { Foo } from './types.d.mts' */
/** @type {(e: unknown) => e is Foo} */
export function isFoo(e) {
return e instanceof Error && 'code' in e && e.code === 'X';
}
🙁 Actual behavior
isFoo.mjs(1,15): error TS6196: 'Foo' is declared but never used.
Foo is used, in the e is Foo type predicate of the @type tag.
🙂 Expected behavior
No error, as in 6.0.3.
Additional information about the issue
Each form below was tested in its own file with the same @import and tsconfig:
| Form | 7.1.0-dev.20260915.1 | 7.0.2 | 6.0.3 |
|---|---|---|---|
@type {(e: unknown) => e is Foo} on a function declaration (above) |
TS6196 | TS6196 | no error |
@type {(e: unknown) => asserts e is Foo} on a function declaration |
TS6196 | TS6196 | no error |
export default /** @type {(e: unknown) => e is Foo} */ (e) => … |
TS6196 | TS6196 | TS6133 |
@param {unknown} e + @returns {e is Foo} |
no error | no error | TS6133 |
JSDoc cast: /** @type {(e: unknown) => e is Foo} */ ((e) => …) |
no error | no error | no error |
@type {(e: Foo) => boolean} (Foo as a parameter type) |
no error | no error | no error |
| the first form, plus a call in the same file that narrows with it | no error | no error | no error |
Workaround: drop the @import and write e is import('./types.d.mts').Foo.
The predicate's type doesn't seem to be checked at all: names that don't exist aren't reported there either, while the same names in the parameter or return type are (same tsconfig, no imports):
// unchecked.mjs
/** @type {(e: unknown) => e is Missing1} */
export function a(e) {
return !!e;
}
/** @type {(e: unknown) => asserts e is Missing2} */
export function b(e) {
if (!e) {
throw new TypeError();
}
}
/** @type {(e: Missing3) => boolean} */
export function c(e) {
return !!e;
}
/** @type {(e: unknown) => Missing4} */
export function d(e) {
return /** @type {never} */ (e);
}
7.1.0-dev.20260915.1 and 7.0.2:
unchecked.mjs(13,16): error TS2304: Cannot find name 'Missing3'.
unchecked.mjs(18,28): error TS2304: Cannot find name 'Missing4'.
6.0.3:
unchecked.mjs(1,33): error TS2304: Cannot find name 'Missing1'.
unchecked.mjs(6,41): error TS2304: Cannot find name 'Missing2'.
unchecked.mjs(13,16): error TS2304: Cannot find name 'Missing3'.
unchecked.mjs(18,28): error TS2304: Cannot find name 'Missing4'.
Possibly relevant, but I haven't confirmed it: when a @type tag supplies a function's FullSignature, the checker only uses it for the argument-count check (checker.go#L3464-L3468, checker.go#L10320-L10324) and never runs checkSourceElement on it. If so, the predicate's type is never checked or marked as referenced unless something else resolves the predicate, like the same-file call in the last row of the table. #64052 (the open fix for #63754) edits these same lines, but only to strip undefined from the @type's type, so it wouldn't change this.
- Ngôn ngữ chính
- Go
- Star
- 111k
- Fork
- 14.4k
- Merge trung bình
- 1 ngày 19 giờ
- Pull request đã merge (30 ngày)
- 117
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.
Issue khác của microsoft/TypeScript
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
microsoft/TypeScript#64322 · 2 bình luận · 1 reaction · 2 người được giao ·
-
Possible Improvement
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
microsoft/TypeScript#64278 · 1 bình luận · 1 reaction ·
-
Docs
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 70/100
microsoft/TypeScript#64118 · 1 bình luận ·
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 88/100
microsoft/TypeScript#64094 ·
-
Docs
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 76/100
microsoft/TypeScript#63959 · 5 bình luận ·
Tất cả issue của microsoft/TypeScript
Issue tương tự
-
Type/Bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 78/100
OpenNSW/nsw-srilanka#497 ·
-
Độ khó 1/5 Dưới một giờ Mức phù hợp với người mới 92/100
milvus-io/birdwatcher#545 ·
-
kind/bug
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
kubernetes-sigs/prow#953 · 1 bình luận ·
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
-
Độ khó 2/5 1-3 giờ Mức phù hợp với người mới 88/100
caddyserver/caddy#8046 ·