YouTip LogoYouTip

Ts Performance

TypeScript project performance optimization involves compilation speed, runtime performance, and code size. This tutorial introduces common performance optimization techniques to help build more efficient TypeScript applications. * * * * * * ## Why Performance Optimization is Needed While TypeScript provides a powerful type system, improper use can affect compilation speed and runtime performance. Compilation of large projects may take several minutes, severely impacting the development experience. The configurations and techniques introduced in this tutorial can significantly improve the performance of TypeScript projects. > **Optimization Goals:** Faster compilation speed, smaller bundle size, higher runtime performance. * * * ## Compilation Configuration Optimization Improve compilation speed by optimizing tsconfig.json configuration. ## tsconfig.json Optimization ```json { "compilerOptions": { // Enable incremental compilation, save previous compilation info "incremental": true, // Skip type checking of node_modules // Greatly improves compilation speed "skipLibCheck": true, // Skip declaration file generation (only generate in final build) "noEmit": true, // Enable fast incremental builds "assumeChangesOnlyAffectDirectDependencies": true, // Execute in parallel "parallel": true, // Enable caching "tsBuildInfoFile": ".tsbuildinfo", // Files that don't need to be resolved "exclude": [ "node_modules", "dist", "build", "**/*.test.ts" ] } } > **skipLibCheck:** This is the most important optimization option, which can reduce compilation time by more than 50%. * * * ## Project References Optimization Use project references to split large projects into smaller modules, enabling incremental compilation. ## packages/utils/tsconfig.json ```json { // Inherit base configuration "extends": "../../tsconfig.base.json", "compilerOptions": { "composite": true, "outDir": "./dist", "declaration": true, "declarationMap": true }, "include": ["src/**/*"], "exclude": ["node_modules", "dist"] } > **composite:** When enabled, TypeScript generates .tsbuildinfo files to accelerate subsequent compilations. * * * ## Type Inference Optimization Make full use of TypeScript's type inference and avoid excessive annotations.

Example

```typescript // Bad practice: excessive type annotations const name: string = "Alice"; const age: number = 25; const isActive: boolean = true; // Good practice: use type inference const name = "Alice"; const age = 25; const isActive = true; // Function return type can be omitted (TypeScript infers automatically) function add(a: number, b: number) { return a + b; } // Complex objects use type inference const user = { id: 1, name: "Bob", email: "bob@example.com" }; // TypeScript infers: // { id: number; name: string; email: string } // Only explicitly annotate when type inference is inaccurate const elements: HTMLElement[] = []; > **Reduce annotations:** TypeScript's type inference is already very intelligent; in most cases explicit type annotations are not needed. * * * ## Avoid Using any Using any loses the advantages of type checking and affects runtime performance. ## Example ```typescript // Bad practice: using any function processData(data: any): any { return data.value; } // Good practice: use unknown or specific types function processData(data: T): string { return data.value; } // If you really don't know the type, use unknown function parseJSON(json: string): unknown { return JSON.parse(json); } // Perform type checking when using const data = parseJSON('{"key": "value"}'); if (typeof data === "object" && data !== null) { const obj = data as { key: string }; console.log(obj.key); } // Better approach: use generics function identity(value: T): T { return value; } const result = identity("hello"); console.log("Result: " + result); > **unknown vs any:** unknown is a type-safe any; type checking is required before use. * * * ## Interface vs Type Alias Choose the appropriate type definition method based on the scenario. ## Example ```typescript // Interface: suitable for defining object types, supports declaration merging interface User { id: number; name: string; } // Extending interface interface User { email: string; } // Type alias: suitable for union types, tuples, function types type ID = string | number; type Status = "pending" | "success" | "error"; type Callback = (data: string) => void; // Utility types usually use type type PartialUser = Partial; type ReadonlyUser = Readonly; // Performance consideration: interfaces usually compile faster than type aliases // For simple object types, use interface interface Point { x: number; y: number; } // For union types, use type type Shape = Circle | Square | Triangle; > **Selection suggestion:** Use interface for object types, type for union types, and type for function types. * * * ## Build Tool Optimization Configure build tools for optimal performance. ## vite.config.ts ```typescript // Import vite import { defineConfig } from 'vite'; import react from '@vitejs/plugin-react'; // Vite configuration optimization export default defineConfig({ plugins: [react()], // Build optimization build: { // Enable code splitting rollupOptions: { output: { // Manual chunk splitting manualChunks: { 'vendor': ['react', 'react-dom'], 'utils': ['lodash', 'axios'] } } }, // Minify code minify: 'terser', // Generate sourcemap sourcemap: false, // Chunk size limit chunkSizeWarningLimit: 500 }, // Development server optimization server: { // Enable hot module replacement hmr: { overlay: true } }, // Optimize dependency resolution optimizeDeps: { include: ['react', 'react-dom'], exclude: ['some-large-library'] } }); > **Code splitting:** Use manualChunks to separate large libraries and reduce main bundle size. * * * ## Tree Shaking Configure modules to support Tree Shaking, eliminating unused code. ## src/utils/index.ts ```typescript // Use ES module exports to support Tree Shaking export function add(a: number, b: number): number { return a + b; } export function subtract(a: number, b: number): number { return a - b; } export function multiply(a: number, b: number): number { return a * b; } export function divide(a: number, b: number): number { if (b === 0) { throw new Error("Cannot divide by zero"); } return a / b; } // Named exports are more conducive to Tree Shaking than default exports // Wrong: export default prevents Tree Shaking // export default { add, subtract, multiply, divide }; // Correct: use named exports console.log("Utility module loaded"); > **Named exports:** Use named exports instead of default exports to allow build tools to better perform Tree Shaking. * * * ## Notes * **skipLibCheck:** Must be enabled in production environment * **Incremental compilation:** Recommended to enable in development environment * **Avoid any:** Use unknown instead * **Tree Shaking:** Use ES modules and named exports > **Best practice:** Set up optimization configurations early in development to avoid later refactoring. * * * ## Summary TypeScript performance optimization involves multiple aspects. * **Compilation optimization:** skipLibCheck, incremental, project references * **Type optimization:** leverage inference, avoid any, choose appropriate type definitions * **Build optimization:** code splitting, Tree Shaking, dependency optimization * **Runtime optimization:** type safety, generic constraints > **Suggestion:** Regularly check compilation time and bundle size, continuously optimize project performance.
← Ts NodejsTs Monorepo β†’