31 — Tooling¶
One line: Each tool around a JavaScript project answers one question the others never check — which versions, which binary, which types, which mistakes, which layout, which syntax, which line runs next — and each can be swapped without touching the language.
The chapter follows a project from its first file to its first bug. It starts with npm: package.json, version ranges and the lockfile, then running tools through npm run and npx. The editor comes next, with the language server behind its red squiggles, then ESLint for mistakes that type-check, Prettier for layout, and bundlers and transpilers for what ships. Debugging with the inspector follows, and last Deno and Bun, two runtimes that run the same language on a different host.
The pages¶
| Page | Level | In one line | Status |
|---|---|---|---|
| npm | 101 | The caret in "^1.2.3" accepts any 1.x.y from 1.2.3 up, but "^0.2.3" stops before 0.3.0 — below 1.0 the caret locks the minor version — and neither admits a prerelease such as 1.3.0-beta.1; the lockfile records what was actually installed. |
stub |
npm run and npx |
101 | npm run puts node_modules/.bin first on PATH — the package's own and every parent folder's — so a script can call tsc by name; npx tsc outside a TypeScript project would fetch the package named tsc, a deprecated 2.0.4 release, which npx --no refuses. |
stub |
| Editor setup | 101 | The red squiggles come from a language server, not from tsc: TypeScript 7 builds one into tsc itself (tsc --lsp --stdio answers as typescript-go), but VS Code and Zed start their own tsserver-based server by default, which can check with a different TypeScript. |
stub |
| ESLint | 201 | tsc --strict exits 0 on a promise nobody awaits, an assignment inside if, a map callback that returns nothing and a variable never read — all type-correct — and ESLint rules such as no-floating-promises and no-cond-assign exist to reject exactly these. |
stub |
| Prettier | 101 | Prettier throws your layout away and reprints the code from its syntax tree, with two exceptions it keeps on purpose: blank lines, several collapsing into one, and an object with a line break after {, which it never joins back onto one line. |
stub |
| Bundlers and transpilers | 201 | A transpiler rewrites syntax for older engines — tsc --target es2019 turns env.PORT ?? "8080" into a !== null && !== void 0 test — and a bundler joins the modules an entry imports into one file; esbuild and Vite do both, without checking types. |
stub |
| Debugging Node | 201 | debugger; is a breakpoint only while a debugger is attached — otherwise Node runs straight past it; node --inspect opens one on ws://127.0.0.1:9229 and keeps running, and --inspect-brk waits there before the first line. |
stub |
| Deno and Bun | 201 | Deno, Bun and Node run the same language on different hosts: Deno refuses file, network and environment access until a flag grants it, a model Node offers only under --permission; and all three run a .ts file by dropping its types, not checking them. |
stub |
Boundaries¶
tsc and tsconfig.json are in TypeScript basics; the type and exports fields of package.json, which Node reads, are in Modules; the built-in test runner is in The Node.js runtime.