TypeScript Performance Optimization: 5 Production Patterns from Compile-Time to Runtime

前端工程

Your TypeScript Project Is Dying a Slow Death

A 100K-line TypeScript project takes 45 seconds for tsc, HMR refreshes lag for 3 seconds, the bundle is 2.4MB, and the production first paint takes 3.8 seconds — this isn't an outlier, it's the reality for most TypeScript projects in 2026. The type system was supposed to be a developer productivity multiplier, but it's become a performance killer. Nobody configures Project References, nobody dares enable skipLibCheck, generics nest five layers deep, runtime type guards sit on hot paths, and the bundle is stuffed with dead code that survived tree-shaking.

This article starts from core concepts and guides you through type checking acceleration → build optimization → runtime performance → memory efficiency → production monitoring with 5 production patterns, from compile-time to runtime, from developer experience to production metrics.


Core Concepts

Concept Description
Type Checking Speed Speed at which the TypeScript compiler checks types, affected by project structure, type complexity, and configuration
Project References Splitting large projects into multiple sub-projects for incremental compilation and parallel type checking
Incremental Build Using caches to re-check only changed portions, avoiding full type checking
Tree-Shaking Build tools identifying and removing unreferenced code to reduce final bundle size
Structural Typing TypeScript's structural type system, determining type compatibility by shape rather than by name
Branded Types Creating nominal types through unique markers, achieving type isolation within a structural type system
Const Assertions as const assertions inferring values as narrowest literal types, reducing type space bloat
Performance Budget Setting budget thresholds for bundle size, compilation time, etc., automatically blocking performance regressions in CI

Optimization Flow

Compile-time optimization:
Project splitting (Project References) → Incremental build → skipLibCheck → Isolated module compilation

Build-time optimization:
tsup/esbuild replacing tsc → Tree-Shaking → Code Splitting → Bundle compression

Runtime optimization:
Avoid hot-path type guards → Efficient generics → Inline type assertions → Reduce runtime type checking

Memory optimization:
Structural type reuse → Branded Types replacing class inheritance → const assertions → Type narrowing

Production monitoring:
Type coverage → Bundle analysis → Performance Budget → CI integration

Problem Analysis: 5 Major TypeScript Performance Bottlenecks

  1. Slow type checking speed: A single large project's full tsc time grows linearly with code volume; a 100K-line project needs 30-60 seconds for tsc, blocking CI pipelines
  2. Bloated build output: tsc only does type checking without tree-shaking; barrel exports cause massive dead code in bundles; runtime type guard code bloat
  3. Runtime performance overhead: Frequent typeof/instanceof checks on hot paths, runtime overhead from deep generic instantiation, excessive class decorator usage
  4. Poor memory efficiency: Complex type inference consumes massive compiler memory, runtime creation of duplicate objects for similar structural types, unused const assertions causing type space bloat
  5. Lack of performance monitoring: No type coverage metrics, no budget control for bundle size, no awareness of compilation time regression, inability to trace production performance issues back to type design

Step-by-Step: 5 Production Patterns

Pattern 1: Type Checking Speed Optimization

// tsconfig.base.json - Base configuration
{
  "compilerOptions": {
    "target": "ES2022",
    "module": "ESNext",
    "moduleResolution": "bundler",
    "strict": true,
    "skipLibCheck": true,
    "incremental": true,
    "tsBuildInfoFile": ".tsbuildinfo",
    "declaration": true,
    "declarationMap": true,
    "sourceMap": true,
    "esModuleInterop": true,
    "forceConsistentCasingInFileNames": true,
    "resolveJsonModule": true,
    "isolatedModules": true
  }
}

// packages/core/tsconfig.json - Core package configuration
{
  "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src"],
  "references": [
    { "path": "../shared" }
  ]
}

// packages/shared/tsconfig.json - Shared package configuration
{
  "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    "composite": true,
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src"]
}

// packages/app/tsconfig.json - Application package configuration
{
  "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    "outDir": "./dist",
    "rootDir": "./src",
    "noEmit": true
  },
  "include": ["src"],
  "references": [
    { "path": "../core" },
    { "path": "../shared" }
  ]
}

// tsconfig.json - Top-level solution configuration
{
  "files": [],
  "references": [
    { "path": "packages/shared" },
    { "path": "packages/core" },
    { "path": "packages/app" }
  ]
}
// scripts/typecheck.ts - Incremental type checking script
import { execSync } from 'child_process';
import { readFileSync, existsSync, unlinkSync } from 'fs';
import { performance } from 'perf_hooks';

interface TypeCheckResult {
  project: string;
  duration: number;
  errors: number;
  cached: boolean;
}

function typecheckProject(projectPath: string, clean: boolean = false): TypeCheckResult {
  const buildInfoFile = `${projectPath}/.tsbuildinfo`;
  const wasCached = existsSync(buildInfoFile) && !clean;

  if (clean && existsSync(buildInfoFile)) {
    unlinkSync(buildInfoFile);
  }

  const start = performance.now();
  let errors = 0;

  try {
    execSync(`npx tsc --build ${projectPath} --verbose`, {
      encoding: 'utf-8',
      stdio: 'pipe',
    });
  } catch (error: any) {
    const output = error.stdout || error.stderr || '';
    const errorMatches = output.match(/error TS\d+:/g);
    errors = errorMatches ? errorMatches.length : 0;
  }

  const duration = performance.now() - start;

  return {
    project: projectPath,
    duration: Math.round(duration),
    errors,
    cached: wasCached,
  };
}

function runFullTypeCheck(clean: boolean = false): void {
  const projects = [
    'packages/shared',
    'packages/core',
    'packages/app',
  ];

  console.log('=== TypeScript Type Check Report ===\n');

  let totalDuration = 0;
  let totalErrors = 0;

  for (const project of projects) {
    const result = typecheckProject(project, clean);
    totalDuration += result.duration;
    totalErrors += result.errors;

    const status = result.errors === 0 ? '✓' : '✗';
    const cacheStatus = result.cached ? '(cached)' : '(full)';
    console.log(
      `${status} ${result.project}: ${result.duration}ms ${cacheStatus}, ${result.errors} errors`
    );
  }

  console.log(`\nTotal: ${totalDuration}ms, ${totalErrors} errors`);

  if (totalDuration > 10000) {
    console.warn('\n⚠️  Type check exceeds 10s budget! Consider:');
    console.warn('  - Adding more project references');
    console.warn('  - Enabling skipLibCheck');
    console.warn('  - Using isolatedModules');
  }
}

const isClean = process.argv.includes('--clean');
runFullTypeCheck(isClean);
// src/types/performance-optimized.ts - Optimized type definitions to reduce checking burden

// ❌ Complex conditional types cause slow type checking
type DeepPartial<T> = T extends object
  ? { [K in keyof T]?: DeepPartial<T[K]> }
  : T;

type DeepRequired<T> = T extends object
  ? { [K in keyof T]-?: DeepRequired<T[K]> }
  : T;

// ✅ Use built-in utility types, avoid repeated instantiation
type CachedPartial<T> = Partial<T>;
type CachedRequired<T> = Required<T>;

// ❌ Excessive recursive type depth
type FlattenDeep<T> = T extends Array<infer U>
  ? FlattenDeep<U>
  : T;

// ✅ Limit recursion depth
type FlattenN<T, N extends number, D extends any[] = []> =
  D['length'] extends N
    ? T
    : T extends Array<infer U>
      ? FlattenN<U, N, [...D, 1]>
      : T;

type Flatten3<T> = FlattenN<T, 3>;

// ❌ Overuse of template literal types
type Route = `/api/${string}/${string}`;

// ✅ Use union types instead of template literals
type ApiRoute =
  | '/api/users'
  | '/api/users/:id'
  | '/api/posts'
  | '/api/posts/:id'
  | '/api/comments'
  | '/api/comments/:id';

// ❌ Large union types
type Status = 'pending' | 'processing' | 'approved' | 'rejected' | 'cancelled' | 'refunded' | 'completed' | 'archived' | 'draft' | 'published';

// ✅ Grouped union types
type OrderStatus = 'pending' | 'processing' | 'completed' | 'cancelled';
type ContentStatus = 'draft' | 'published' | 'archived';
type PaymentStatus = 'approved' | 'rejected' | 'refunded';

// skipLibCheck-optimized .d.ts
declare module 'heavy-lib' {
  export interface HeavyConfig {
    readonly apiKey: string;
    readonly endpoint: string;
    readonly timeout: number;
    readonly retries: number;
  }

  export function createClient(config: HeavyConfig): HeavyClient;

  export interface HeavyClient {
    getData<T>(id: string): Promise<T>;
    setData<T>(id: string, data: T): Promise<void>;
  }
}

Pattern 2: Build Optimization with tsup/esbuild

// tsup.config.ts - tsup build configuration
import { defineConfig } from 'tsup';

export default defineConfig([
  {
    entry: ['src/index.ts'],
    format: ['esm', 'cjs'],
    dts: {
      resolve: true,
      compilerOptions: {
        skipLibCheck: true,
        composite: false,
      },
    },
    splitting: true,
    treeshake: true,
    minify: true,
    sourcemap: true,
    clean: true,
    outDir: 'dist',
    target: 'es2022',
    platform: 'node',
    external: ['react', 'react-dom'],
    esbuildOptions(options) {
      options.logLevel = 'info';
      options.chunkNames = 'chunks/[name]-[hash]';
    },
  },
  {
    entry: ['src/browser.ts'],
    format: ['esm'],
    treeshake: true,
    minify: true,
    sourcemap: true,
    outDir: 'dist/browser',
    target: 'es2022',
    platform: 'browser',
    esbuildOptions(options) {
      options.conditions = ['browser'];
    },
  },
]);
// src/index.ts - Optimized export structure for tree-shaking

// ❌ barrel exports break tree-shaking
// export * from './utils';
// export * from './validators';
// export * from './transformers';

// ✅ Explicit named exports for bundler dependency analysis
export { validateEmail, validateUrl } from './validators/email';
export { validateAge, validateRange } from './validators/number';
export { formatDate, parseDate } from './transformers/date';
export { formatCurrency, parseCurrency } from './transformers/currency';

// ✅ Use conditional exports to reduce browser bundle
export type { UserSchema, CreateUserInput } from './types/user';
export type { PaginationParams, SearchParams } from './types/pagination';
// scripts/bundle-analysis.ts - Bundle analysis script
import { build } from 'esbuild';
import { readFileSync, writeFileSync } from 'fs';
import { gzipSync } from 'zlib';

interface BundleMetrics {
  name: string;
  size: number;
  gzipSize: number;
  modules: number;
}

const BUDGET = {
  maxBundleSize: 100 * 1024,
  maxGzipSize: 30 * 1024,
  maxChunkSize: 50 * 1024,
};

async function analyzeBundle(entryPoint: string): Promise<BundleMetrics> {
  const result = await build({
    entryPoints: [entryPoint],
    bundle: true,
    minify: true,
    write: false,
    metafile: true,
    format: 'esm',
    target: 'es2022',
    external: ['react', 'react-dom'],
  });

  const outputFiles = result.outputFiles || [];
  const metafile = result.metafile;

  let totalSize = 0;
  for (const file of outputFiles) {
    totalSize += file.contents.byteLength;
  }

  const gzipSize = gzipSync(Buffer.from(outputFiles[0]?.contents || [])).byteLength;

  const moduleCount = metafile ? Object.keys(metafile.inputs).length : 0;

  return {
    name: entryPoint,
    size: totalSize,
    gzipSize,
    modules: moduleCount,
  };
}

async function runBundleAnalysis(): Promise<void> {
  console.log('=== Bundle Analysis Report ===\n');

  const entryPoints = [
    'src/index.ts',
    'src/browser.ts',
  ];

  let hasViolation = false;

  for (const entry of entryPoints) {
    const metrics = await analyzeBundle(entry);

    const sizeKB = (metrics.size / 1024).toFixed(1);
    const gzipKB = (metrics.gzipSize / 1024).toFixed(1);

    console.log(`${entry}:`);
    console.log(`  Size: ${sizeKB}KB (budget: ${BUDGET.maxBundleSize / 1024}KB)`);
    console.log(`  Gzip: ${gzipKB}KB (budget: ${BUDGET.maxGzipSize / 1024}KB)`);
    console.log(`  Modules: ${metrics.modules}`);

    if (metrics.size > BUDGET.maxBundleSize) {
      console.warn(`  ⚠️  Bundle size exceeds budget!`);
      hasViolation = true;
    }

    if (metrics.gzipSize > BUDGET.maxGzipSize) {
      console.warn(`  ⚠️  Gzip size exceeds budget!`);
      hasViolation = true;
    }

    console.log();
  }

  if (hasViolation) {
    console.error('❌ Performance budget violated!');
    process.exit(1);
  } else {
    console.log('✅ All bundles within budget.');
  }
}

runBundleAnalysis();
// package.json - Optimized build scripts
{
  "scripts": {
    "typecheck": "tsc --build",
    "typecheck:clean": "tsc --build --clean && tsc --build",
    "build": "tsup",
    "build:analyze": "tsup --metafile && node scripts/bundle-analysis.ts",
    "dev": "tsup --watch",
    "check:all": "npm run typecheck && npm run build && npm run test",
    "prepack": "npm run build"
  }
}

Pattern 3: Runtime Performance Optimization

// src/runtime/hot-path.ts - Hot path type guard optimization

// ❌ Complex type guards on hot paths
function processData(data: unknown): ProcessedData {
  if (
    typeof data === 'object' &&
    data !== null &&
    'id' in data &&
    typeof (data as any).id === 'string' &&
    'name' in data &&
    typeof (data as any).name === 'string' &&
    'age' in data &&
    typeof (data as any).age === 'number' &&
    'email' in data &&
    typeof (data as any).email === 'string'
  ) {
    return data as ProcessedData;
  }
  throw new Error('Invalid data');
}

// ✅ Minimized type guard, trusting compile-time types
interface ProcessedData {
  id: string;
  name: string;
  age: number;
  email: string;
}

function processDataOptimized(data: unknown): ProcessedData {
  if (typeof data !== 'object' || data === null) {
    throw new Error('Expected object');
  }
  return data as ProcessedData;
}

// ✅ Layered validation: fast check on hot paths, strict validation on cold paths
function processHotPath(data: unknown): ProcessedData {
  if (typeof data !== 'object' || data === null) {
    throw new Error('Expected object');
  }
  return data as ProcessedData;
}

function processColdPath(data: unknown): ProcessedData {
  const result = ProcessedDataSchema.safeParse(data);
  if (!result.success) {
    throw new Error(`Validation failed: ${result.error.message}`);
  }
  return result.data;
}

import { z } from 'zod';

const ProcessedDataSchema = z.object({
  id: z.string().uuid(),
  name: z.string().min(1),
  age: z.number().int().min(0),
  email: z.string().email(),
});
// src/runtime/generics.ts - Efficient generic patterns

// ❌ Generic class instantiation causes runtime bloat
class DataStore<T> {
  private items: T[] = [];

  add(item: T): void {
    this.items.push(item);
  }

  get(index: number): T | undefined {
    return this.items[index];
  }

  filter(predicate: (item: T) => boolean): T[] {
    return this.items.filter(predicate);
  }

  map<U>(transform: (item: T) => U): U[] {
    return this.items.map(transform);
  }

  reduce<U>(reducer: (acc: U, item: T) => U, initial: U): U {
    return this.items.reduce(reducer, initial);
  }
}

// ✅ Use functional utilities instead of generic classes
interface DataStore {
  readonly items: readonly unknown[];
}

function createStore<T>(initialItems: T[] = []): DataStore {
  return { items: Object.freeze([...initialItems]) };
}

function addItem<T>(store: DataStore, item: T): DataStore {
  return { items: Object.freeze([...store.items, item]) };
}

function getItem<T>(store: DataStore, index: number): T {
  return store.items[index] as T;
}

function filterItems<T>(store: DataStore, predicate: (item: T) => boolean): T[] {
  return store.items.filter(predicate as (item: unknown) => boolean) as T[];
}

// ✅ Use conditional types instead of runtime branching
type Result<T, E = Error> =
  | { readonly ok: true; readonly value: T }
  | { readonly ok: false; readonly error: E };

function ok<T>(value: T): Result<T> {
  return { ok: true, value };
}

function err<E>(error: E): Result<never, E> {
  return { ok: false, error };
}

function mapResult<T, U, E>(result: Result<T, E>, fn: (value: T) => U): Result<U, E> {
  return result.ok ? ok(fn(result.value)) : result;
}

function flatMapResult<T, U, E>(
  result: Result<T, E>,
  fn: (value: T) => Result<U, E>
): Result<U, E> {
  return result.ok ? fn(result.value) : result;
}

// ✅ Avoid runtime type erasure overhead
interface TypeTag<T extends string> {
  readonly __type: T;
}

type UserId = string & TypeTag<'UserId'>;
type OrderId = string & TypeTag<'OrderId'>;

function createUserId(id: string): UserId {
  return id as UserId;
}

function createOrderId(id: string): OrderId {
  return id as OrderId;
}

function getUser(id: UserId): Promise<User | null> {
  return Promise.resolve(null);
}

function getOrder(id: OrderId): Promise<Order | null> {
  return Promise.resolve(null);
}

interface User {
  id: UserId;
  name: string;
}

interface Order {
  id: OrderId;
  total: number;
}
// src/runtime/iteration.ts - Efficient iteration patterns

// ❌ Creating new arrays on each iteration
function processUsers(users: User[]): ProcessedUser[] {
  return users
    .filter((u) => u.age >= 18)
    .map((u) => ({ ...u, displayName: u.name.toUpperCase() }))
    .filter((u) => u.displayName.length > 0)
    .map((u) => ({ ...u, score: calculateScore(u) }));
}

// ✅ Single-pass replaces multiple chained calls
function processUsersOptimized(users: User[]): ProcessedUser[] {
  const result: ProcessedUser[] = [];

  for (const u of users) {
    if (u.age < 18) continue;

    const displayName = u.name.toUpperCase();
    if (displayName.length === 0) continue;

    result.push({
      ...u,
      displayName,
      score: calculateScore(u),
    });
  }

  return result;
}

// ✅ Use generators for lazy computation
function* filterUsers(users: Iterable<User>): Generator<User> {
  for (const u of users) {
    if (u.age >= 18) yield u;
  }
}

function* mapUsers(users: Iterable<User>): Generator<ProcessedUser> {
  for (const u of users) {
    yield {
      ...u,
      displayName: u.name.toUpperCase(),
      score: calculateScore(u),
    };
  }
}

function processUsersLazy(users: User[]): ProcessedUser[] {
  return [...mapUsers(filterUsers(users))];
}

interface ProcessedUser extends User {
  displayName: string;
  score: number;
}

function calculateScore(user: User): number {
  return user.name.length * user.age;
}

Pattern 4: Memory Efficiency Optimization

// src/memory/structural-typing.ts - Structural type reuse

// ❌ Each interface defined independently, compiler creates separate types
interface UserResponse {
  id: string;
  name: string;
  email: string;
  role: 'admin' | 'editor' | 'viewer';
  createdAt: string;
}

interface UserListItem {
  id: string;
  name: string;
  email: string;
  role: 'admin' | 'editor' | 'viewer';
  createdAt: string;
}

interface UserProfile {
  id: string;
  name: string;
  email: string;
  role: 'admin' | 'editor' | 'viewer';
  createdAt: string;
  bio: string;
  avatar: string;
}

// ✅ Use base types + composition for reuse
interface BaseEntity {
  readonly id: string;
  readonly createdAt: string;
  readonly updatedAt: string;
}

type UserRole = 'admin' | 'editor' | 'viewer';

interface UserBase extends BaseEntity {
  readonly name: string;
  readonly email: string;
  readonly role: UserRole;
}

type UserResponse = UserBase;
type UserListItem = UserBase;

interface UserProfile extends UserBase {
  readonly bio: string;
  readonly avatar: string;
}

// ✅ Use Pick/Omit to derive from base types
type UserSummary = Pick<UserBase, 'id' | 'name' | 'role'>;
type UserEmailInfo = Pick<UserBase, 'id' | 'email'>;
type UserWithoutRole = Omit<UserBase, 'role'>;
// src/memory/branded-types.ts - Branded Types replacing class inheritance

// ❌ Class inheritance causes runtime prototype chain overhead
class Entity {
  constructor(
    public id: string,
    public createdAt: Date,
  ) {}
}

class UserEntity extends Entity {
  constructor(
    id: string,
    createdAt: Date,
    public name: string,
    public email: string,
  ) {
    super(id, createdAt);
  }
}

class OrderEntity extends Entity {
  constructor(
    id: string,
    createdAt: Date,
    public total: number,
    public status: string,
  ) {
    super(id, createdAt);
  }
}

// ✅ Use Branded Types + pure data objects
interface Brand<T extends string> {
  readonly __brand: T;
}

type Branded<T, B extends string> = T & Brand<B>;

type UserId = Branded<string, 'UserId'>;
type OrderId = Branded<string, 'OrderId'>;
type ProductId = Branded<string, 'ProductId'>;

function createUserId(id: string): UserId {
  if (!/^[0-9a-f]{8}-[0-9a-f]{4}-4[0-9a-f]{3}-[89ab][0-9a-f]{3}-[0-9a-f]{12}$/i.test(id)) {
    throw new Error('Invalid UUID format for UserId');
  }
  return id as UserId;
}

function createOrderId(id: string): OrderId {
  if (!/^ORD-\d{8}$/.test(id)) {
    throw new Error('Invalid order ID format');
  }
  return id as OrderId;
}

interface User {
  readonly id: UserId;
  readonly name: string;
  readonly email: string;
  readonly role: UserRole;
}

interface Order {
  readonly id: OrderId;
  readonly userId: UserId;
  readonly total: number;
  readonly status: OrderStatus;
  readonly items: ReadonlyArray<OrderItem>;
}

type OrderStatus = 'pending' | 'processing' | 'shipped' | 'delivered' | 'cancelled';

interface OrderItem {
  readonly productId: ProductId;
  readonly quantity: number;
  readonly unitPrice: number;
}

// ✅ Branded Types ensure type safety with zero runtime overhead
function getUserOrders(userId: UserId, orders: ReadonlyArray<Order>): ReadonlyArray<Order> {
  return orders.filter((o) => o.userId === userId);
}

// Compile-time prevention of ID misuse
// getUserOrders(createOrderId('ORD-20260616'), orders); // ❌ Type error
// src/memory/const-assertions.ts - const assertions optimization

// ❌ Broad types cause compiler to create many type instances
const ROUTES = {
  users: '/api/users',
  posts: '/api/posts',
  comments: '/api/comments',
};

type RouteKey = keyof typeof ROUTES; // string
type RouteValue = typeof ROUTES[keyof typeof ROUTES]; // string

// ✅ const assertion locks literal types
const ROUTES = {
  users: '/api/users',
  posts: '/api/posts',
  comments: '/api/comments',
} as const;

type RouteKey = keyof typeof ROUTES; // 'users' | 'posts' | 'comments'
type RouteValue = typeof ROUTES[keyof typeof ROUTES]; // '/api/users' | '/api/posts' | '/api/comments'

// ✅ const assertion + satisfies pattern
const HTTP_METHODS = ['GET', 'POST', 'PUT', 'DELETE', 'PATCH'] as const;
type HttpMethod = typeof HTTP_METHODS[number]; // 'GET' | 'POST' | 'PUT' | 'DELETE' | 'PATCH'

const STATUS_CODES = {
  OK: 200,
  CREATED: 201,
  BAD_REQUEST: 400,
  UNAUTHORIZED: 401,
  FORBIDDEN: 403,
  NOT_FOUND: 404,
  INTERNAL_ERROR: 500,
} as const;

type StatusCode = typeof STATUS_CODES[keyof typeof STATUS_CODES];
// 200 | 201 | 400 | 401 | 403 | 404 | 500

// ✅ Use satisfies to ensure correct types while preserving literal types
const API_CONFIG = {
  baseUrl: 'https://api.example.com',
  timeout: 5000,
  retries: 3,
  headers: {
    'Content-Type': 'application/json',
    'Accept': 'application/json',
  },
} as const satisfies Record<string, string | number | Record<string, string>>;

type ApiConfigKey = keyof typeof API_CONFIG; // 'baseUrl' | 'timeout' | 'retries' | 'headers'

// ✅ Freeze objects to prevent runtime modification
const IMMUTABLE_CONFIG = Object.freeze({
  MAX_RETRIES: 3,
  TIMEOUT_MS: 5000,
  PAGE_SIZE: 20,
  MAX_PAGE_SIZE: 100,
} as const);

type Config = typeof IMMUTABLE_CONFIG;
// src/memory/type-narrowing.ts - Efficient type narrowing

// ❌ Repeated type guards
function handleData(data: unknown): string {
  if (typeof data === 'object' && data !== null && 'type' in data) {
    if ((data as any).type === 'user') {
      if (typeof (data as any).name === 'string') {
        return (data as any).name;
      }
    }
    if ((data as any).type === 'order') {
      if (typeof (data as any).id === 'string') {
        return (data as any).id;
      }
    }
  }
  return 'unknown';
}

// ✅ Use discriminated unions + type guard functions
interface UserData {
  readonly type: 'user';
  readonly name: string;
  readonly email: string;
}

interface OrderData {
  readonly type: 'order';
  readonly id: string;
  readonly total: number;
}

type AppData = UserData | OrderData;

function isUserData(data: AppData): data is UserData {
  return data.type === 'user';
}

function isOrderData(data: AppData): data is OrderData {
  return data.type === 'order';
}

function handleDataOptimized(data: AppData): string {
  switch (data.type) {
    case 'user':
      return data.name;
    case 'order':
      return data.id;
  }
}

// ✅ Use type predicate caching
type TypeGuard<T> = (value: unknown) => value is T;

function createTypeGuard<T>(check: (value: unknown) => boolean): TypeGuard<T> {
  return (value: unknown): value is T => check(value);
}

const isString = createTypeGuard<string>((v) => typeof v === 'string');
const isNumber = createTypeGuard<number>((v) => typeof v === 'number');
const isBoolean = createTypeGuard<boolean>((v) => typeof v === 'boolean');

function parseEnvValue<T>(
  value: string | undefined,
  guard: TypeGuard<T>,
  defaultValue: T,
): T {
  if (value === undefined) return defaultValue;
  const parsed: unknown = value;
  return guard(parsed) ? parsed : defaultValue;
}

const port = parseEnvValue(process.env.PORT, isNumber, 3000);
const debug = parseEnvValue(process.env.DEBUG, isBoolean, false);

Pattern 5: Production Monitoring and Performance Budgets

// scripts/type-coverage.ts - Type coverage checking
import { execSync } from 'child_process';

interface TypeCoverageResult {
  totalFiles: number;
  typedFiles: number;
  coverage: number;
  anyCount: number;
  unsafeCount: number;
}

function checkTypeCoverage(): TypeCoverageResult {
  try {
    const output = execSync(
      'npx type-coverage --detail --at-least 95',
      { encoding: 'utf-8', stdio: 'pipe' }
    );

    const match = output.match(/(\d+)\/(\d+) files/);
    const anyMatch = output.match(/(\d+) any/);

    const typedFiles = match ? parseInt(match[1], 10) : 0;
    const totalFiles = match ? parseInt(match[2], 10) : 0;
    const anyCount = anyMatch ? parseInt(anyMatch[1], 10) : 0;

    return {
      totalFiles,
      typedFiles,
      coverage: totalFiles > 0 ? (typedFiles / totalFiles) * 100 : 0,
      anyCount,
      unsafeCount: anyCount,
    };
  } catch {
    return {
      totalFiles: 0,
      typedFiles: 0,
      coverage: 0,
      anyCount: -1,
      unsafeCount: -1,
    };
  }
}

function reportTypeCoverage(): void {
  const result = checkTypeCoverage();

  console.log('=== Type Coverage Report ===\n');
  console.log(`Files: ${result.typedFiles}/${result.totalFiles}`);
  console.log(`Coverage: ${result.coverage.toFixed(1)}%`);
  console.log(`Any count: ${result.anyCount}`);

  if (result.coverage < 95) {
    console.warn('\n⚠️  Type coverage below 95%!');
    console.warn('  Run `npx type-coverage --detail` to find untyped code.');
  }

  if (result.coverage < 80) {
    console.error('❌ Type coverage critically low!');
    process.exit(1);
  }
}

reportTypeCoverage();
// scripts/performance-budget.ts - Performance budget CI check
import { readFileSync } from 'fs';
import { gzipSync } from 'zlib';

interface PerformanceBudget {
  maxBundleSize: number;
  maxGzipSize: number;
  maxTypeCheckTime: number;
  minTypeCoverage: number;
  maxChunkCount: number;
}

const DEFAULT_BUDGET: PerformanceBudget = {
  maxBundleSize: 100 * 1024,       // 100KB
  maxGzipSize: 30 * 1024,          // 30KB
  maxTypeCheckTime: 15000,         // 15s
  minTypeCoverage: 95,             // 95%
  maxChunkCount: 10,
};

interface BudgetCheckResult {
  metric: string;
  value: number;
  budget: number;
  unit: string;
  passed: boolean;
}

function checkBundleBudget(
  bundlePath: string,
  budget: PerformanceBudget = DEFAULT_BUDGET,
): BudgetCheckResult[] {
  const results: BudgetCheckResult[] = [];

  try {
    const content = readFileSync(bundlePath);
    const size = content.byteLength;
    const gzipSize = gzipSync(content).byteLength;

    results.push({
      metric: 'Bundle Size',
      value: size,
      budget: budget.maxBundleSize,
      unit: 'bytes',
      passed: size <= budget.maxBundleSize,
    });

    results.push({
      metric: 'Gzip Size',
      value: gzipSize,
      budget: budget.maxGzipSize,
      unit: 'bytes',
      passed: gzipSize <= budget.maxGzipSize,
    });
  } catch {
    results.push({
      metric: 'Bundle Size',
      value: -1,
      budget: budget.maxBundleSize,
      unit: 'bytes',
      passed: false,
    });
  }

  return results;
}

function checkTypeCheckBudget(
  budget: PerformanceBudget = DEFAULT_BUDGET,
): BudgetCheckResult {
  const start = Date.now();
  try {
    execSync('npx tsc --noEmit', { encoding: 'utf-8', stdio: 'pipe' });
  } catch {
    // type errors are handled separately
  }
  const duration = Date.now() - start;

  return {
    metric: 'Type Check Time',
    value: duration,
    budget: budget.maxTypeCheckTime,
    unit: 'ms',
    passed: duration <= budget.maxTypeCheckTime,
  };
}

function runPerformanceBudget(): void {
  console.log('=== Performance Budget Check ===\n');

  const results: BudgetCheckResult[] = [
    ...checkBundleBudget('dist/index.js'),
    checkTypeCheckBudget(),
  ];

  let allPassed = true;

  for (const result of results) {
    const status = result.passed ? '✓' : '✗';
    const valueStr = result.value >= 0
      ? result.unit === 'bytes'
        ? `${(result.value / 1024).toFixed(1)}KB`
        : `${result.value}${result.unit}`
      : 'N/A';
    const budgetStr = result.unit === 'bytes'
      ? `${(result.budget / 1024).toFixed(1)}KB`
      : `${result.budget}${result.unit}`;

    console.log(`${status} ${result.metric}: ${valueStr} (budget: ${budgetStr})`);

    if (!result.passed) {
      allPassed = false;
    }
  }

  if (!allPassed) {
    console.error('\n❌ Performance budget violated!');
    process.exit(1);
  } else {
    console.log('\n✅ All performance budgets met.');
  }
}

import { execSync } from 'child_process';
runPerformanceBudget();
// .github/workflows/typescript-perf.yml - CI performance monitoring
// GitHub Actions workflow configuration
/*
name: TypeScript Performance

on:
  pull_request:
    paths:
      - '**.ts'
      - '**.tsx'
      - 'tsconfig*.json'
      - 'package.json'

jobs:
  performance:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v4
      - uses: actions/setup-node@v4
        with:
          node-version: 22
          cache: npm

      - run: npm ci
      - name: Type Check
        run: |
          START=$(date +%s%N)
          npx tsc --noEmit
          END=$(date +%s%N)
          DURATION=$(( (END - START) / 1000000 ))
          echo "Type check duration: ${DURATION}ms"
          if [ $DURATION -gt 15000 ]; then
            echo "::error::Type check exceeds 15s budget (${DURATION}ms)"
            exit 1
          fi

      - name: Type Coverage
        run: |
          npx type-coverage --at-least 95 || {
            echo "::error::Type coverage below 95%"
            exit 1
          }

      - name: Bundle Analysis
        run: |
          npm run build
          node scripts/performance-budget.ts

      - name: Comment PR
        uses: actions/github-script@v7
        with:
          script: |
            const fs = require('fs');
            const report = fs.readFileSync('perf-report.txt', 'utf8');
            github.rest.issues.createComment({
              owner: context.repo.owner,
              repo: context.repo.repo,
              issue_number: context.issue.number,
              body: `## 📊 TypeScript Performance Report\n${report}`
            });
*/
// src/monitoring/runtime-metrics.ts - Runtime performance metric collection
interface PerformanceMetric {
  name: string;
  value: number;
  timestamp: number;
  tags: Record<string, string>;
}

class PerformanceCollector {
  private metrics: PerformanceMetric[] = [];
  private readonly maxMetrics = 1000;

  recordMetric(name: string, value: number, tags: Record<string, string> = {}): void {
    this.metrics.push({
      name,
      value,
      timestamp: Date.now(),
      tags,
    });

    if (this.metrics.length > this.maxMetrics) {
      this.metrics = this.metrics.slice(-this.maxMetrics);
    }
  }

  timeAsync<T>(name: string, fn: () => Promise<T>, tags?: Record<string, string>): Promise<T> {
    const start = performance.now();
    return fn().finally(() => {
      const duration = performance.now() - start;
      this.recordMetric(name, duration, { ...tags, unit: 'ms' });
    });
  }

  timeSync<T>(name: string, fn: () => T, tags?: Record<string, string>): T {
    const start = performance.now();
    try {
      return fn();
    } finally {
      const duration = performance.now() - start;
      this.recordMetric(name, duration, { ...tags, unit: 'ms' });
    }
  }

  getMetrics(name?: string): PerformanceMetric[] {
    if (name) {
      return this.metrics.filter((m) => m.name === name);
    }
    return [...this.metrics];
  }

  getAverage(name: string): number {
    const named = this.getMetrics(name);
    if (named.length === 0) return 0;
    return named.reduce((sum, m) => sum + m.value, 0) / named.length;
  }

  getP95(name: string): number {
    const named = this.getMetrics(name);
    if (named.length === 0) return 0;
    const sorted = named.map((m) => m.value).sort((a, b) => a - b);
    const index = Math.ceil(sorted.length * 0.95) - 1;
    return sorted[index];
  }

  generateReport(): string {
    const metricNames = [...new Set(this.metrics.map((m) => m.name))];
    const lines: string[] = ['### Runtime Performance Report\n'];

    for (const name of metricNames) {
      const avg = this.getAverage(name).toFixed(2);
      const p95 = this.getP95(name).toFixed(2);
      const count = this.getMetrics(name).length;
      lines.push(`- **${name}**: avg=${avg}ms, p95=${p95}ms, n=${count}`);
    }

    return lines.join('\n');
  }
}

const perfCollector = new PerformanceCollector();

async function fetchWithMetrics<T>(
  url: string,
  schema: z.ZodSchema<T>,
): Promise<T> {
  return perfCollector.timeAsync(
    'api.fetch',
    async () => {
      const response = await fetch(url);
      const raw = await response.json();
      const result = schema.safeParse(raw);
      if (!result.success) {
        throw new Error(`API validation failed: ${result.error.message}`);
      }
      return result.data;
    },
    { url: new URL(url).pathname },
  );
}

Common Pitfalls

Pitfall 1: skipLibCheck Causing Type Unsafety

// ❌ Global skipLibCheck disables all .d.ts checking
// tsconfig.json
{
  "compilerOptions": {
    "skipLibCheck": true  // Disables all library type checking
  }
}

// ✅ skipLibCheck only skips node_modules .d.ts, your own .d.ts still needs checking
// tsconfig.json
{
  "compilerOptions": {
    "skipLibCheck": true  // Safe: only affects node_modules
  }
}
// Your own types directory configured separately with strict checking
// types/tsconfig.json
{
  "compilerOptions": {
    "strict": true,
    "skipLibCheck": false
  }
}

Pitfall 2: Barrel Exports Breaking Tree-Shaking

// ❌ Re-exporting all modules in index.ts
// src/index.ts
export * from './users';
export * from './orders';
export * from './products';
export * from './analytics';

// ✅ Explicit on-demand exports
// src/index.ts
export { UserService } from './users/service';
export { OrderService } from './orders/service';
export type { User, CreateUserInput } from './users/types';
export type { Order, CreateOrderInput } from './orders/types';

// ✅ Configure sideEffects in package.json
// package.json
{
  "sideEffects": false,
  "module": "./dist/index.mjs",
  "exports": {
    ".": {
      "import": "./dist/index.mjs",
      "require": "./dist/index.cjs"
    },
    "./users": {
      "import": "./dist/users.mjs"
    }
  }
}

Pitfall 3: Incomplete Project References Configuration

// ❌ Missing composite option causes reference to fail
// packages/shared/tsconfig.json
{
  "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    "outDir": "./dist"
    // Missing "composite": true
  }
}

// ✅ Referenced projects must enable composite
// packages/shared/tsconfig.json
{
  "extends": "../../tsconfig.base.json",
  "compilerOptions": {
    "composite": true,
    "declaration": true,
    "declarationMap": true,
    "outDir": "./dist",
    "rootDir": "./src"
  },
  "include": ["src"]
}

Pitfall 4: Excessive Runtime Type Guards

// ❌ Full type checking on every loop iteration
function processItems(items: unknown[]): Result[] {
  return items.map((item) => {
    const validated = ItemSchema.parse(item);  // Full validation every time
    return transform(validated);
  });
}

// ✅ Validate once at entry, trust types internally
function processItems(items: unknown[]): Result[] {
  const validated = z.array(ItemSchema).parse(items);  // One-time validation
  return validated.map(transform);
}

// ✅ Or use layered validation
function processItems(items: unknown[]): Result[] {
  return items.map((item) => {
    if (!isPlainObject(item)) throw new Error('Invalid item');
    return transform(item as Item);
  });
}

function isPlainObject(value: unknown): value is Record<string, unknown> {
  return typeof value === 'object' && value !== null && !Array.isArray(value);
}

Pitfall 5: Ignoring Compiler Memory Limits

// ❌ Default 1.5GB memory insufficient for large projects
// Running tsc causes memory overflow
// FATAL ERROR: Reached heap limit Allocation failed - JavaScript heap out of memory

// ✅ Increase Node.js memory limit
// package.json
{
  "scripts": {
    "typecheck": "NODE_OPTIONS='--max-old-space-size=4096' tsc --build",
    "typecheck:ci": "NODE_OPTIONS='--max-old-space-size=8192' tsc --build"
  }
}

// ✅ Split projects to reduce per-compiler memory requirements
// Use Project References to split large projects into multiple sub-projects
// Each sub-project compiles independently, significantly reducing peak memory

Error Troubleshooting Table

Error Symptom Possible Cause Solution
tsc exceeds 30 seconds Single large project without Project References Split into multiple sub-projects, enable incremental compilation
error TS6307 Project References missing composite Add "composite": true to referenced project
Abnormally large bundle Barrel exports breaking tree-shaking Switch to explicit named exports, configure sideEffects
Slow HMR refresh tsc full re-check Enable incremental and isolatedModules
FATAL ERROR: Reached heap limit Compiler memory overflow Increase --max-old-space-size or split project
Type inference timeout Excessive recursive type depth Limit recursion depth, use FlattenN<T, 3>
Type instantiation is excessively deep Nested conditional types too deep Simplify type logic, use intermediate type aliases
Poor runtime performance Frequent type guards on hot paths Layered validation, minimize hot path checks
Type errors after skipLibCheck Custom .d.ts has issues Configure custom types directory with separate strict checking
Unused code in bundle tsconfig importsNotUsedAsValues Use tsup/esbuild instead of tsc for bundling

Advanced Optimization

Compiler Performance Tuning

// tsconfig.perf.json - Maximum performance configuration
{
  "extends": "./tsconfig.base.json",
  "compilerOptions": {
    "incremental": true,
    "tsBuildInfoFile": "./.tsbuildinfo",
    "skipLibCheck": true,
    "isolatedModules": true,
    "verbatimModuleSyntax": true,
    "noEmit": true,
    "assumeChangesOnlyAffectDirectDependencies": true,
    "disableSourceOfProjectReferenceRedirect": true,
    "disableReferencedProjectLoad": true
  }
}

// scripts/tsc-watch.ts - Smart incremental watcher
import { watch } from 'chokidar';
import { execSync } from 'child_process';
import { relative, dirname, extname } from 'path';
import { performance } from 'perf_hooks';

interface WatchConfig {
  include: string[];
  exclude: string[];
  debounceMs: number;
  projects: Record<string, string[]>;
}

const watchConfig: WatchConfig = {
  include: ['src/**/*.ts'],
  exclude: ['src/**/*.test.ts', 'src/**/*.spec.ts'],
  debounceMs: 300,
  projects: {
    'packages/shared': ['packages/shared/src/**/*.ts'],
    'packages/core': ['packages/core/src/**/*.ts'],
    'packages/app': ['packages/app/src/**/*.ts'],
  },
};

let debounceTimer: NodeJS.Timeout | null = null;

function getAffectedProject(filePath: string): string | null {
  for (const [project, patterns] of Object.entries(watchConfig.projects)) {
    for (const pattern of patterns) {
      const dir = pattern.replace('/**/*.ts', '');
      if (filePath.startsWith(dir)) {
        return project;
      }
    }
  }
  return null;
}

function typecheckAffected(filePath: string): void {
  const project = getAffectedProject(filePath);
  if (!project) return;

  const start = performance.now();
  try {
    execSync(`npx tsc --build ${project}`, { encoding: 'utf-8', stdio: 'pipe' });
    const duration = (performance.now() - start).toFixed(0);
    console.log(`✓ ${project}: ${duration}ms`);
  } catch (error: any) {
    const duration = (performance.now() - start).toFixed(0);
    console.error(`✗ ${project}: ${duration}ms`);
    console.error(error.stdout || error.message);
  }
}

const watcher = watch(watchConfig.include, {
  ignored: watchConfig.exclude,
  persistent: true,
  ignoreInitial: true,
});

watcher.on('change', (filePath) => {
  if (debounceTimer) clearTimeout(debounceTimer);
  debounceTimer = setTimeout(() => {
    typecheckAffected(filePath);
  }, watchConfig.debounceMs);
});

watcher.on('add', (filePath) => {
  typecheckAffected(filePath);
});

console.log('🔍 Watching for TypeScript changes...');

Bundle Optimization Strategies

// scripts/advanced-bundle-opt.ts - Advanced bundle optimization
import { build, Plugin } from 'esbuild';

const sizeLimitPlugin: Plugin = {
  name: 'size-limit',
  setup(build) {
    build.onEnd((result) => {
      for (const output of result.outputFiles || []) {
        const sizeKB = output.contents.byteLength / 1024;
        const path = output.path;

        if (sizeKB > 50) {
          console.warn(`⚠️  ${path}: ${sizeKB.toFixed(1)}KB exceeds 50KB chunk limit`);
        }
      }
    });
  },
};

const deadCodeEliminationPlugin: Plugin = {
  name: 'dead-code-elimination',
  setup(build) {
    build.onEnd((result) => {
      const content = result.outputFiles?.[0]?.text || '';
      const deadCodePatterns = [
        /if\s*\(\s*false\s*\)/g,
        /if\s*\(\s*true\s*\)\s*\{/g,
        /\/\/\s*@ts-ignore/g,
      ];

      for (const pattern of deadCodePatterns) {
        const matches = content.match(pattern);
        if (matches && matches.length > 0) {
          console.warn(`⚠️  Potential dead code: ${matches.length} occurrences of ${pattern}`);
        }
      }
    });
  },
};

async function buildOptimized(): Promise<void> {
  await build({
    entryPoints: ['src/index.ts'],
    bundle: true,
    minify: true,
    treeShaking: true,
    format: 'esm',
    target: 'es2022',
    outdir: 'dist',
    metafile: true,
    splitting: true,
    plugins: [sizeLimitPlugin, deadCodeEliminationPlugin],
    external: ['react', 'react-dom', 'zod'],
    define: {
      'process.env.NODE_ENV': '"production"',
    },
    logLevel: 'info',
  });
}

buildOptimized();

Runtime Performance Profiling

// src/monitoring/profiler.ts - Runtime performance profiler
interface ProfileEntry {
  operation: string;
  startTime: number;
  endTime: number;
  duration: number;
  memoryBefore: number;
  memoryAfter: number;
  memoryDelta: number;
}

class RuntimeProfiler {
  private entries: ProfileEntry[] = [];
  private readonly maxEntries = 500;

  profile<T>(operation: string, fn: () => T): T {
    const memBefore = process.memoryUsage().heapUsed;
    const startTime = performance.now();

    try {
      return fn();
    } finally {
      const endTime = performance.now();
      const memAfter = process.memoryUsage().heapUsed;

      this.entries.push({
        operation,
        startTime,
        endTime,
        duration: endTime - startTime,
        memoryBefore: memBefore,
        memoryAfter: memAfter,
        memoryDelta: memAfter - memBefore,
      });

      if (this.entries.length > this.maxEntries) {
        this.entries = this.entries.slice(-this.maxEntries);
      }
    }
  }

  async profileAsync<T>(operation: string, fn: () => Promise<T>): Promise<T> {
    const memBefore = process.memoryUsage().heapUsed;
    const startTime = performance.now();

    try {
      return await fn();
    } finally {
      const endTime = performance.now();
      const memAfter = process.memoryUsage().heapUsed;

      this.entries.push({
        operation,
        startTime,
        endTime,
        duration: endTime - startTime,
        memoryBefore: memBefore,
        memoryAfter: memAfter,
        memoryDelta: memAfter - memBefore,
      });

      if (this.entries.length > this.maxEntries) {
        this.entries = this.entries.slice(-this.maxEntries);
      }
    }
  }

  getHotspots(thresholdMs: number = 10): ProfileEntry[] {
    return this.entries
      .filter((e) => e.duration > thresholdMs)
      .sort((a, b) => b.duration - a.duration);
  }

  getMemoryHotspots(thresholdBytes: number = 1024 * 100): ProfileEntry[] {
    return this.entries
      .filter((e) => e.memoryDelta > thresholdBytes)
      .sort((a, b) => b.memoryDelta - a.memoryDelta);
  }

  generateReport(): string {
    const lines: string[] = [
      '### Runtime Performance Profile\n',
      '#### Time Hotspots (>10ms)',
    ];

    for (const entry of this.getHotspots()) {
      lines.push(
        `- **${entry.operation}**: ${entry.duration.toFixed(2)}ms, ` +
        `memory: ${(entry.memoryDelta / 1024).toFixed(1)}KB`
      );
    }

    lines.push('\n#### Memory Hotspots (>100KB)');
    for (const entry of this.getMemoryHotspots()) {
      lines.push(
        `- **${entry.operation}**: ${(entry.memoryDelta / 1024).toFixed(1)}KB, ` +
        `time: ${entry.duration.toFixed(2)}ms`
      );
    }

    return lines.join('\n');
  }
}

const profiler = new RuntimeProfiler();

// Usage example
const users = profiler.profile('fetchUsers', () => {
  return Array.from({ length: 1000 }, (_, i) => ({
    id: `user-${i}`,
    name: `User ${i}`,
    email: `user${i}@example.com`,
  }));
});

const result = profiler.profile('processUsers', () => {
  return users.filter((u) => u.email.includes('example')).map((u) => u.name);
});

console.log(profiler.generateReport());

Solution Comparison

Optimization Dimension tsc Incremental Project References tsup/esbuild Vite Turbopack
Compilation Speed ★★★ ★★★★ ★★★★★ ★★★★★ ★★★★★
Configuration Complexity Low Medium Low Low Low
Incremental Support Yes Yes No (full but very fast) Yes Yes
Type Checking Built-in Built-in External (tsc) External (tsc) External (tsc)
Tree-Shaking No No Yes Yes Yes
Bundle Size N/A N/A Excellent Excellent Excellent
Use Case Library dev Large projects Library/Tools Web apps Next.js
Production Ready ★★★★★ ★★★★★ ★★★★★ ★★★★★ ★★★★
Runtime Optimization Type Guard Optimization Branded Types const assertions Generators Layered Validation
Performance Gain ★★★★ ★★★ ★★ ★★★ ★★★★
Code Intrusion Medium Low Low Medium Medium
Type Safety ★★★ ★★★★★ ★★★★★ ★★★ ★★★★
Learning Cost Low Low Low Medium Low
Use Case Hot paths ID types Constant config Large datasets API boundaries

TypeScript performance optimization isn't "icing on the cake" — it's the "lifeline" of production projects. At compile-time, use Project References and incremental compilation for 10x speedup; at build-time, replace tsc with tsup/esbuild for tree-shaking; at runtime, avoid hot-path type guards; for memory, use Branded Types and const assertions to reduce bloat; in production, use performance budgets and type coverage to guard the baseline. Performance isn't optimized — it's designed. Configure Project References from day one, use explicit exports from the first module, and use const assertions from the first type.


  • JSON Formatter — Format tsconfig and build output JSON, quickly troubleshoot configuration issues
  • Code Formatter — Format TypeScript code, unify team code style
  • cURL to Code — Convert API requests to type-safe TypeScript fetch code

Try these browser-local tools — no sign-up required →

#TypeScript性能#类型优化#编译加速#运行时优化#TypeScript 5.5#2026#前端工程