jsconfig.json option

moduleResolution

  • Default node10
  • Tested with TypeScript 5.9

moduleResolution is the lookup algorithm: given "./format" or "some-package/sub", which file does the import mean? nodenext applies Node's rules (extensions required in ES modules, exports maps honored); bundler applies the looser rules bundlers share (extensions optional, exports read with the import condition).

module: "nodenext" implies nodenext and module: "preserve" implies bundler, so most configs never write it. bundler arrived with TypeScript 5.0. The old node10 (also spelled node) ignores exports maps and is deprecated from TypeScript 6.0; classic is removed there.

At a glance

Write Usually nothing: let module imply it. Write "bundler" next to module: "esnext"
On the command line --moduleResolution
Type string
Default in TypeScript 5.9 node10 (with module: "commonjs"; module nodenext implies nodenext, and preserve implies bundler)
TypeScript's description Specify how TypeScript looks up a file from a given module specifier.
In the quick-start setups

The description is quoted from TypeScript's own option list (Apache-2.0); see the notices. The setup values are the checked configs on the quick-start pages.

Examples

main.js Error confirmed 5.9.3 TypeScript 5.9.3, run 21 October 2026: main.js(2,29): error TS2835: Relative import paths need explicit file extensions in ECMAScript imports when '--moduleResolution' is 'node16' or 'nodenext'. Did you mean './format.js'? 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. main.js(2,29): error TS2835: Relative import paths need explicit file extensions in ECMAScript imports when '--moduleResolution' is 'node16' or 'nodenext'. Did you mean './format.js'? 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. main.js(2,29): error TS2835: Relative import paths need explicit file extensions in ECMAScript imports when '--moduleResolution' is 'node16' or 'nodenext'. Did you mean './format.js'? checked 21 October 2026
import { formatPrice } from "./format";error TS2835: Relative import paths need explicit file extensions in ECMAScript imports when '--moduleResolution' is 'node16' or 'nodenext'. Did you mean './format.js'?

console.log(formatPrice(1999));
moduleResolution nodenext: a relative import needs its extension.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "nodenext",
    "types": []
  },
  "include": [
    "*.js"
  ]
}
main.js TypeScript 5.9.3 TypeScript 5.9.3, run 21 October 2026: No errors. 6.0.3 TypeScript 6.0.3, run 21 October 2026: the same as 5.9.3. No errors. 7.0.2 TypeScript 7.0.2, run 21 October 2026: the same as 5.9.3. No errors. checked 21 October 2026
import { formatPrice } from "./format";

console.log(formatPrice(1999));
moduleResolution bundler: an import without its extension passes, because a bundler fills it in.
jsconfig.json for this example
{
  "compilerOptions": {
    "checkJs": true,
    "noEmit": true,
    "strict": true,
    "target": "es2022",
    "module": "preserve",
    "types": [],
    "moduleResolution": "bundler"
  },
  "include": [
    "*.js"
  ]
}

Which one matches your project

Choose by who resolves the imports when the code runs. If Node.js loads your files directly, use nodenext, so the checker refuses imports that Node.js would refuse. If a bundler, Bun, or a framework's build resolves them, use bundler, so the checker accepts what that tool accepts. A browser that loads <script type="module"> files without a bundler needs exact relative URLs, which nodenext with "type": "module" enforces; TypeScript's handbook suggests that pairing for unbundled browser code.

Gotchas

  • With bundler, the checker accepts import "./format", but Node.js would not. Use it only for code that something other than Node.js resolves.
  • An import the checker cannot resolve is an error only when it binds something; import "./polyfill.js" with a wrong path passes unless noUncheckedSideEffectImports is on.

Sources

Last reviewed 20 October 2026.