~/hackweb.dev
TypeScript Best Practices
Quiz
...

TypeScript Best Practices

beginner · updated Tue Sep 08 2026Contribute

Write clean, maintainable, and type-safe TypeScript code.

TypeScript Best Practices

Guidelines for writing effective, maintainable, and type-safe TypeScript code.

Enable Strict Mode

Always enable strict mode in tsconfig.json:

{
  "compilerOptions": {
    "strict": true,
    "noImplicitAny": true,
    "strictNullChecks": true
  }
}

Remember: Strict mode catches the most common bugs and ensures all types are explicit.

Avoid any

Use specific types, unknown, or generics instead:

// Bad
function process(data: any): any { return data; }

// Good
function process(data: { name: string; age: number }): string {
  return `${data.name} is ${data.age}`;
}

// Better — unknown + type guard
function process(data: unknown): string {
  if (typeof data === "string") return data;
  return "Unknown";
}

Use Interfaces for Object Shapes

Interfaces support declaration merging, extending, and class implementation:

interface User {
  name: string;
  age: number;
}

interface Admin extends User {
  role: string;
}

Tip: Prefer interfaces over type aliases for object shapes that might be extended.

Annotate Function Signatures

Always annotate parameters and return types to document your API:

function calculateTotal(items: { price: number }[], taxRate: number): number {
  return items.reduce((sum, item) => sum + item.price, 0) * (1 + taxRate);
}

Use Discriminated Unions

Cleaner than complex if/else chains:

type Shape =
  | { kind: "circle"; radius: number }
  | { kind: "rectangle"; width: number; height: number };

function getArea(shape: Shape): number {
  switch (shape.kind) {
    case "circle": return Math.PI * shape.radius ** 2;
    case "rectangle": return shape.width * shape.height;
  }
}

Use Partial for Optional Parameters

Partial makes all properties optional while keeping types safe:

interface Options {
  timeout: number;
  retries: number;
  debug: boolean;
}

function configure(options: Partial<Options>): void {
  const defaults: Options = { timeout: 5000, retries: 3, debug: false };
  const settings = { ...defaults, ...options };
}

Best Practices

  • Enable strict mode always
  • Avoid any — use specific types, unknown, or generics
  • Use interfaces for object shapes
  • Annotate function signatures
  • Use as const for literal types
  • Prefer discriminated unions over complex conditionals
  • Use Partial for optional parameter objects
  • Generate declaration files for libraries
  • Run the linter to enforce consistent style

Common Mistakes

  • Using any excessively defeats TypeScript’s purpose
  • Not enabling strict mode misses many type errors
  • Overusing type assertions bypasses type safety
  • Ignoring compiler warnings leads to hidden bugs
  • Not using return type annotations misses type mismatches