Rules Hub
Coding Rules Library
Rule priority, scope & exceptions
Use this to align rules with the senior-level structure (P0/P1/P2, scope, exceptions/tradeoffs).
Use .js extension on relative imports in ESM TypeScript projects
Under NodeNext/ESM resolution, relative imports must end in .js (the compiled output), even when the source is .ts and even in test files.
Bad example
| 1 | // project uses "module": "NodeNext" / "type": "module" |
| 2 | import { UserService } from '../services/user-service'; |
| 3 | import type { User } from '../types/user-types.ts'; |
Explanation (EN)
Omitting the extension (or pointing at the .ts source) breaks Node's ESM resolution at runtime, since the emitted JS imports resolve against compiled .js files. TypeScript will not rewrite these specifiers for you.
Objašnjenje (HR)
Izostavljanje ekstenzije (ili upucivanje na .ts izvor) lomi Nodeovu ESM rezoluciju u runtimeu, jer se importi u generiranom JS-u rjesavaju prema kompajliranim .js datotekama. TypeScript nece prepisati te specifikatore umjesto tebe.
Good example
| 1 | // project uses "module": "NodeNext" / "type": "module" |
| 2 | import { UserService } from '../services/user-service.js'; |
| 3 | import type { User } from '../types/user-types.js'; |
Explanation (EN)
The .js extension matches the compiled output and resolves correctly at runtime. Apply it uniformly to every relative import, including spec/test files, so the pattern stays consistent.
Objašnjenje (HR)
Ekstenzija .js odgovara kompajliranom izlazu i ispravno se rjesava u runtimeu. Primijeni je jednoliko na svaki relativni import, ukljucujuci spec/test datoteke, da obrazac ostane dosljedan.
Notes (EN)
This applies to relative specifiers only; bare package imports keep their normal form. Editor 'fix import' actions often drop the extension, so double-check after auto-imports.
Bilješke (HR)
Vrijedi samo za relativne specifikatore; importi paketa zadrzavaju uobicajeni oblik. Editorske 'fix import' akcije cesto izostave ekstenziju, pa provjeri nakon auto-importa.
Exceptions / Tradeoffs (EN)
Bundler-based setups (e.g. Vite/Webpack with classic bundler resolution) may not require the extension; this rule targets Node's NodeNext/ESM resolution.
Iznimke / Tradeoffi (HR)
Postavke temeljene na bundleru (npr. Vite/Webpack s klasicnom bundler rezolucijom) mozda ne trebaju ekstenziju; ovo pravilo cilja Nodeovu NodeNext/ESM rezoluciju.