xerrion/typescript-rules icon
public
Published on 4/16/2025
TypeScript Rules

Rules

TypeScript Best Practices

Critical Rules

  • Use strict type checking with "strict": true in tsconfig.json
  • Prefer interfaces over type aliases for object definitions that may be extended
  • Always define explicit return types for functions and methods
  • Use union types instead of enums for simple flag values
  • Leverage discriminated unions for complex state management
  • Never use any type - use unknown for truly unknown types
  • Always handle null and undefined cases explicitly
  • Use readonly modifiers for immutable properties and arrays
  • Implement error handling with custom error types
  • Use type guards for runtime type checking
  • Keep generics simple and well-constrained
  • Use Pick, Omit, Partial and other utility types when appropriate
  • Document complex types and ALL public functions classes and interfaces with JSDoc comments

Examples

<example> // Good - Using interface with explicit types interface UserState { readonly id: string; name: string; email: string | null; preferences: ReadonlyArray<string>; }

// Good - Discriminated union with type guard interface RequestPending { status: 'pending'; }

interface RequestSuccess { status: 'success'; data: UserState; }

interface RequestError { status: 'error'; error: Error; }

type RequestState = RequestPending | RequestSuccess | RequestError;

function isSuccess(state: RequestState): state is RequestSuccess { return state.status === 'success'; }

// Good - Generic with constraints function getProperty<T, K extends keyof T>(obj: T, key: K): T[K] { return obj[key]; } </example>

<example type="invalid"> // Bad - Using any type function processData(data: any) { return data.someProperty; }

// Bad - Not handling null case function getUserName(user: { name: string | null }): string { return user.name.toUpperCase(); // Might crash }

// Bad - Using type assertion without checking function processResponse(response: unknown) { const data = response as { id: number }; return data.id; }

// Bad - Mutable array without type safety const items = []; items.push(123); items.push('string'); // Mixed types array </example>