Files
open-design/scripts
Leon AburimeandLA 8d20f5566b feat(guard): catch @ts-nocheck files with unresolved relative imports (#5164)
* feat(guard): catch @ts-nocheck files with unresolved relative imports

`// @ts-nocheck` disables all type checking for a file, including TS2307
"Cannot find module". That silently hides broken relative imports: a barrel
move or file rename can leave a @ts-nocheck module importing a path that no
longer resolves, and `pnpm typecheck` stays green while the module fails to
load at runtime. tsc also never verifies the specifier of a dynamic import()
even in a fully-checked file.

Add a guard check (wired into `pnpm guard` and its unit-test list) that
re-establishes the one guarantee @ts-nocheck removes: every relative import /
export-from / import-type / dynamic import() specifier in a @ts-nocheck
TypeScript source must resolve to a real module on disk. NodeNext .js -> .ts
mapping, extensionless directory-index barrels, and asset extensions are all
handled; string literals in comments/expressions are ignored (AST-based).

Clean on the current tree: 33 @ts-nocheck files, 0 violations.

* fix(guard): resolve .mjs/.cjs imports extension-specifically

Review follow-up (#5164): resolvesRelativeSpecifier mapped .js/.mjs/.cjs to
one broad candidate list, so `import './x.mjs'` passed whenever `x.ts` existed
and `./x.cjs` whenever `x.ts`/`x.mts` existed — but NodeNext emits .mjs only
from .mts and .cjs only from .cts (a same-basename .ts emits .js), so those
imports fail at runtime. That was a false negative in the guard's core promise.

Split candidates by requested JS extension: .js -> [.ts,.tsx,.js,.jsx],
.jsx -> [.tsx,.jsx], .mjs -> [.mts,.mjs], .cjs -> [.cts,.cjs]. Add fixture
assertions for the accepted matches and the rejected .mjs/.cjs mismatches.

---------

Co-authored-by: LA <la@LAs-MacBook-Pro.lan>
2026-07-14 03:20:35 +00:00
..