import { db } from "./db"; // the file is src/db.ts
Compile error: relative ESM imports need an explicit extension, so write
./db.jsIt is a compile error, and you must write ./db.js. Node's ESM loader does not guess file extensions. tsc does not add them either. So TypeScript requires the extension that the emitted file will have. You write ./db.js, and TypeScript maps it to db.ts for type checking.
"tsc adds .js to the specifier in the output" is wrong, because tsc never rewrites import paths here. "Node resolves ./db to ./db.js at runtime" is wrong, because Node's ESM loader does not guess extensions. "you must write ./db.ts" is wrong, because the import must name the emitted .js file.
Read more