Deck 15 - Tooling/Config (React+TS Ecosystem) (objective)
Goal: review and debug React+TS tooling like a senior: tsconfig, bundlers, linting, tests, env vars, builds, and dependency hygiene.
You learn: what/why (under the hood), common breakages, and evaluator-grade review wording.
Output style: PASS/PARTIAL/FAIL + 2-3 issues + fix approach.
Mental model: what tsconfig controls.
tsconfig controls TypeScript type checking + emit settings.
Why: it defines strictness, module resolution, and what code TS outputs (if emitting).
Mental model: bundler vs TypeScript compiler.
Bundler (Vite/Webpack) builds and serves your app.
TS compiler checks types; bundler transpiles (often via esbuild/swc) and may not enforce full type checking unless configured.
Mental model: dev server vs production build.
Dev server optimizes for fast reload; production build optimizes for size/perf.
Bugs can appear only in prod (minification, tree-shaking, different env vars).
Mental model: module resolution (Node vs bundler).
Resolution strategy impacts how imports are found (paths, extensions, package.json exports).
Misconfig causes ‘module not found’ or wrong entry selection.
Mental model: ESM vs CJS (why it matters).
ESM uses import/export; CJS uses require/module.exports.
Mixing can break tooling; bundlers handle it but some libs/configs are sensitive.
Mental model: dependency graph + lockfile.
package.json declares direct deps; lockfile pins transitive deps.
Lockfile changes can alter runtime even if your code did not change.
Mental model: tree-shaking (high level).
Bundlers remove unused exports when code is ESM and side-effects are known.
Poorly structured imports can prevent tree-shaking and bloat bundles.
Mental model: source maps (why you care).
Source maps map bundled code back to original sources.
Essential for debugging production errors and stack traces.
Mental model: environment variables are build-time in the browser.
Client env vars get baked into the bundle.
Never put secrets in client env vars; treat them as public.
Mental model: lint vs typecheck vs tests.
Lint: style/some correctness. Typecheck: TS compile-time safety. Tests: runtime behavior.
All three catch different classes of issues.
Mental model: transpilation does not equal type safety.
esbuild/swc can transpile TS without type checking.
Senior: ensure CI runs tsc –noEmit (or equivalent) to enforce types.
Mental model: hydration/SSR differences (tooling angle).
SSR requires consistent render output; some libraries behave differently on server.
Config (target, polyfills) can affect runtime compatibility.
Mental model: browser targets affect output.
Build targets control what syntax/polyfills are emitted.
Wrong targets can break older browsers or bloat bundles unnecessarily.
Mental model: workspace/monorepo tooling risk.
Multiple packages can create version mismatches and duplicate deps.
Review peerDeps and ensure single React version to avoid hooks errors.
Mental model: why ‘Invalid hook call’ happens.
Common causes: multiple React copies, mismatched react/react-dom versions, or improper bundling.
Tooling review: check lockfile and dependency tree.
Mental model: bundler plugins are code execution.
Plugins run during build; they can introduce security and stability risks.
Prefer trusted plugins and pin versions.
Mental model: config changes can be breaking changes.
tsconfig/eslint/vite config changes can change behavior without touching app code.
Reviewer: demand rationale and ensure CI proves safety.
Mental model: why CI parity matters.
Local builds can differ from CI due to Node version, env vars, or caching.
Pin Node versions and keep scripts deterministic.
Mental model: minimize build-time magic.
Complex config increases fragility.
Senior: keep config small, documented, and tested in CI.
tsconfig: strict mode (why).
strict enables many safety checks (nulls, implicit any, etc.).
Senior: treat strictness as correctness; relax only with explicit, justified exceptions.
tsconfig: strictNullChecks (impact).
Forces you to handle null/undefined explicitly.
Prevents runtime crashes in React (data loads asynchronously).
tsconfig: noImplicitAny (impact).
Prevents implicit any from spreading.
Senior: reduces type holes that cause runtime errors.
tsconfig: noUncheckedIndexedAccess (why useful).
Indexing returns T | undefined.
Prevents ‘cannot read property’ bugs when keys are missing.