← Back to Index

Chapter 8: Tooling and Build

Building an efficient TypeScript development workflow

1. Advanced tsconfig.json

Beyond basic configuration — master key options that affect project structure and compilation behavior.

{
  "compilerOptions": {
    "target": "ES2022",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "lib": ["ES2022"],
    "outDir": "dist",
    "rootDir": "src",
    "strict": true,
    "incremental": true,
    "tsBuildInfoFile": "./dist/.tsbuildinfo",

    "paths": {
      "@/*": ["./src/*"],
      "@utils/*": ["./src/utils/*"]
    },
    "baseUrl": ".",

    "exactOptionalPropertyTypes": true,
    "noUncheckedIndexedAccess": true,
    "noUnusedLocals": true,
    "noUnusedParameters": true
  },
  "include": ["src/**/*"],
  "exclude": ["node_modules", "dist"]
}

paths Path Aliases

Use @/utils/... instead of ../../../utils/...

incremental Incremental Compilation

Caches compilation info, 50%+ faster rebuilds for large projects

noUncheckedIndexedAccess

Array/object index access returns T | undefined, safer

target vs lib

target controls output syntax level, lib controls available type declarations

2. ESLint

ESLint with typescript-eslint catches potential issues during coding. The new Flat Config format is recommended.

npm install -D eslint @eslint/js typescript-eslint
// eslint.config.js
import eslint from "@eslint/js";
import tseslint from "typescript-eslint";

export default tseslint.config(
    eslint.configs.recommended,
    ...tseslint.configs.recommended,
    {
        rules: {
            "@typescript-eslint/no-unused-vars": ["error", {
                argsIgnorePattern: "^_",
            }],
            "@typescript-eslint/explicit-function-return-type": "warn",
            "@typescript-eslint/no-explicit-any": "error",
            "no-console": ["warn", { allow: ["warn", "error"] }],
        },
    },
    {
        ignores: ["dist/", "node_modules/"],
    }
);
npx eslint .          # 检查所有文件
npx eslint --fix .    # 自动修复可修复的问题

3. Prettier

Prettier handles code formatting — unified style, ending pointless formatting debates.

npm install -D prettier eslint-config-prettier
// .prettierrc
{
  "semi": true,
  "singleQuote": false,
  "tabWidth": 4,
  "trailingComma": "all",
  "printWidth": 100,
  "arrowParens": "always"
}

Add eslint-config-prettier to ESLint config to disable rules that conflict with Prettier:

// eslint.config.js 中追加
import prettier from "eslint-config-prettier";

export default tseslint.config(
    // ...其他配置
    prettier, // 放在最后,覆盖冲突规则
);

Set up Format on Save in your editor for automatic formatting on save.

4. Build Tool Comparison

tsc

官方

TypeScript compiler. Type checking + transpilation. Average speed, but the only tool that does complete type checking.

Recommended: Type checking in CI

esbuild

极快

Written in Go, 10-100x faster than webpack. No type checking, only transpilation and bundling.

Recommended: Library bundling, fast builds

swc

Rust

Rust-based transpiler, speed close to esbuild. Used by default in Next.js.

Recommended: Fast transpilation replacing Babel

Vite

全能

Uses native ESM for instant HMR in development, Rollup for production bundling.

Recommended: Frontend project dev + build

Recommended combo: Use tsc --noEmit for type checking + esbuild or Vite for bundling/running during development. Similar to Java's separation of "compile check (javac) + build tool (Maven/Gradle)".

5. npm Package Publishing

When publishing TypeScript packages, you need to provide both compiled JS and type declaration files.

// package.json 关键字段
{
  "name": "my-ts-lib",
  "version": "1.0.0",
  "main": "dist/index.js",
  "types": "dist/index.d.ts",
  "exports": {
    ".": {
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs",
      "types": "./dist/index.d.ts"
    }
  },
  "files": ["dist"],
  "scripts": {
    "build": "tsc",
    "prepublishOnly": "npm run build"
  }
}
npm login
npm publish     # 发布到 npm registry

The files field specifies files to include in the package — more intuitive than .npmignore, whitelist over blacklist.

6. Docker Deployment

Multi-stage build: first stage compiles TypeScript, second stage only keeps runtime JS files, significantly reducing image size.

# Dockerfile
# ===== 构建阶段 =====
FROM node:20-alpine AS builder
WORKDIR /app

COPY package*.json ./
RUN npm ci

COPY tsconfig.json ./
COPY src/ ./src/
RUN npm run build

# ===== 生产阶段 =====
FROM node:20-alpine AS production
WORKDIR /app

COPY package*.json ./
RUN npm ci --omit=dev

COPY --from=builder /app/dist ./dist

ENV NODE_ENV=production
EXPOSE 3000

USER node
CMD ["node", "dist/index.js"]
# 构建并运行
docker build -t my-ts-app .
docker run -p 3000:3000 --env-file .env my-ts-app

Benefits of Multi-stage Build

  • Production image excludes TypeScript source and devDependencies
  • Image size can drop from ~800MB to ~150MB
  • Run with USER node, avoiding execution as root

📝 Chapter Summary & Tutorial Complete

tsconfig determines project quality

Enable strict + extra strict options, the sooner the better

ESLint + Prettier golden combo

ESLint for logic quality, Prettier for format consistency

tsc checking + esbuild bundling

Type safety and build speed combined

Docker multi-stage build

Separate compilation from runtime, lean and secure images

🎉

Congratulations on completing the tutorial!

You've mastered the complete knowledge chain of TypeScript from basic syntax to project deployment.

Suggested next steps:

  • Build a complete REST API project with TypeScript
  • Explore advanced frameworks like NestJS or tRPC
  • Learn advanced TypeScript type gymnastics (type-level programming)
  • Contribute to open source projects, read excellent TS code