Skip to content

/config/typescript/tsconfig-moduleresolution

tsconfig moduleResolution: bundler, nodenext, node16

verified onenvironmentlocal · windows 10.0.26200 arm64 · GNU bash 5.3.15 (Git Bash) · v24.20.0updated 2026-10-20
tool
TypeScript
file
tsconfig.json
key
compilerOptions.moduleResolution
type
"bundler" | "node16" | "nodenext"

compilerOptions.moduleResolution decides how the TypeScript compiler turns an import specifier such as "./util" or "react" into a file on disk. In TypeScript 7 the valid values are bundler, node16 and nodenext; node10 (alias node) and classic were removed.

Which value to use

  • bundler: the code is built by a bundler (Vite, webpack, esbuild, Bun, Next.js). Supports package.json exports, and does not require file extensions in relative imports.
  • nodenext: Node.js runs the emitted JavaScript. Follows Node's rules: ES modules need explicit extensions, exports and imports are honoured. Must be paired with "module": "nodenext".
  • node16: like nodenext but frozen to Node 16 behaviour. Must be paired with "module": "node16".

Valid combinations with module (TypeScript 7.0.2)

Each cell was checked with tsc 7.0.2 on an empty project:

moduleResolutionmodule esnextmodule commonjsmodule nodenext
bundlerokokerror TS5095
nodenexterror TS5110error TS5110ok
node16error TS5110error TS5110ok
node / node10error TS5108 (removed)error TS5108error TS5108
classicerror TS5108 (removed)error TS5108error TS5108
bash
npm init -y >/dev/null
npm install --silent --no-audit --no-fund typescript@7.0.2 >/dev/null 2>&1
echo 'export const x: number = 1;' > a.ts
for pair in esnext:bundler nodenext:nodenext esnext:nodenext; do
  m=${pair%:*}; mr=${pair#*:}
  echo "{ \"compilerOptions\": { \"module\": \"$m\", \"moduleResolution\": \"$mr\", \"noEmit\": true } }" > tsconfig.json
  echo "module=$m moduleResolution=$mr:"; npx tsc && echo "  ok"
done; true

Output

module=esnext moduleResolution=bundler:
  ok
module=nodenext moduleResolution=nodenext:
  ok
module=esnext moduleResolution=nodenext:
tsconfig.json(1,34): error TS5110: Option 'module' must be set to 'NodeNext' when option 'moduleResolution' is set to 'NodeNext'.

Example: a Vite or webpack project

tsconfig.json
{
  "compilerOptions": {
    "target": "es2022",
    "module": "esnext",
    "moduleResolution": "bundler",
    "noEmit": true
  }
}

Pitfalls

  • bundler with "module": "nodenext" fails with TS5095: bundler resolution only works with preserve, commonjs, or es2015 and later.
  • With nodenext, an ES module import of ./util must be written ./util.js, even though the source file is util.ts.
  • On TypeScript 6, node10 and classic still work behind "ignoreDeprecations": "6.0"; on TypeScript 7 they are gone (TS5108).

Sources