Learning Guides
Menu

Writing and Running Your Code

3 min readEffective TypeScript

Writing and Running Your Code

TypeScript is a toolchain, not just a language. This chapter covers how to configure, run, and maintain TypeScript in real projects.

Item 55: Use a Single tsconfig.json Source of Truth

Keep compiler settings in one place and share them across tools.

JSON
{
  "compilerOptions": {
    "target": "ES2020",
    "module": "ESNext",
    "moduleResolution": "Bundler",
    "strict": true,
    "noUncheckedIndexedAccess": true
  }
}

If you need multiple configs, extend a base file:

JSON
// tsconfig.base.json
{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true
  }
}

Item 56: Let tsc Type‑Check, Let the Bundler Emit

Use tsc --noEmit in CI and rely on your bundler (Next, Vite, Webpack) for output.

BASH
pnpm tsc --noEmit

This prevents conflicts in output settings and keeps builds fast.

Item 57: Use tsx or ts-node for Small Scripts

For CLI scripts and tooling:

BASH
pnpm add -D tsx
tsx scripts/generate.ts

Use ts-node only if you need full TypeScript compiler behavior.

Item 58: Turn On Source Maps for Debugging

JSON
{
  "compilerOptions": {
    "sourceMap": true
  }
}

This makes stack traces and browser debugging map to TypeScript lines.

Item 59: Prefer @ts-expect-error Over @ts-ignore

@ts-expect-error fails if the error disappears, preventing stale ignores.

TYPESCRIPT
// @ts-expect-error: temporary migration workaround
legacyThing();

Item 60: Add ESLint for Non‑Type Errors

TypeScript does not catch everything (e.g., unused vars, async mistakes). Linting fills the gap:

JSON
{
  "extends": ["next", "next/core-web-vitals"]
}

Item 61: Use isolatedModules for Babel/Vite Builds

If you transpile with Babel or SWC, turn this on:

JSON
{
  "compilerOptions": {
    "isolatedModules": true
  }
}

It prevents patterns that only tsc can handle (like const enum).

Item 62: Use Project References for Large Repos

Project references speed builds and enforce boundaries:

JSON
{
  "references": [{ "path": "./packages/shared" }]
}

Use composite: true in referenced projects.

Item 63: Include Type Tests in CI

Type tests catch API regressions without running code.

TYPESCRIPT
// type-tests.ts
expectType<Promise<User>>(fetchUser("1"));

Item 64: Treat Compiler Errors as Design Feedback

When TypeScript complains, it's often a chance to simplify types or make APIs more precise. This mindset keeps your codebase healthy.

Key Takeaways

  1. Centralize compiler config and share it.
  2. Use tsc --noEmit for type checking.
  3. Use a TS runtime for scripts (tsx/ts-node).
  4. Turn on source maps for debugging.
  5. Prefer @ts-expect-error with reasons.
  6. Lint for non-type issues.
  7. Use project references in large repos.

Next: strategies for migrating existing JavaScript to TypeScript.