jcnavarrete/typescript-rules icon
public
Published on 5/22/2025
Typescript Rules

Rules
Adhere to these TypeScript coding best practices and guardrails for high-quality, maintainable, scalable, and robust applications. These guidelines foster a "top senior TypeScript expert Agent" mindset, emphasizing type safety, clarity, and modern standards.

### **TypeScript Coding Best Practices and Guardrails**

**1. Embrace Strict Type Safety:**

* **Eliminate `any`:** Strictly avoid `any`. Figure out the right typing; if not possible, use `unknown`, `object`, or `Record<string, unknown>`. Cast `unknown` values only after runtime type checks.

* **Explicit Typing:** Explicitly declare types for function parameters, return values, and complex objects to improve readability and prevent subtle errors.

* **Leverage Advanced Types:** Utilize generics, conditional types, mapped types, discriminated unions, and utility types (e.g., `Partial<T>`, `Required<T>`) for robust type safety and reusability.

* **`strictNullChecks`:** Always enable `strictNullChecks` in `tsconfig.json`. Use optional chaining (`?.`) and nullish coalescing (`??`).

**2. Adhere to ESLint and Code Style:**

* **Respect ESLint Configuration:** Strictly follow all rules in `eslint.config.ts` (or `.eslintrc.js`), including `@typescript-eslint/recommended` and `@typescript-eslint/recommended-requiring-type-checking`.

* **Automated Formatting:** Integrate a code formatter (e.g., Prettier) for consistent style.

* **Avoid Unused Code:** Eliminate unused imports, variables, functions, and classes. ESLint rules should enforce this.

* **Consistent Naming:** Use clear, descriptive, and consistent naming (e.g., `PascalCase` for types, `camelCase` for variables/functions).

**3. Code Structure and Modularity:**

* **Single Responsibility Principle (SRP):** Each file, function, or class should have a single, well-defined responsibility.

* **Modular Design:** Break features into smaller, independent, testable, and reusable modules.

* **Clear Exports/Imports:** Be explicit about exports and imports. Prefer named exports for clarity.

* **Interface vs. Type Aliases:** Prefer `interface` for object shapes; `type` for unions, intersections, and primitive aliases.

**4. Immutability and Side Effects:**

* **Prefer `const` and `readonly`:** Use `const` for unchangeable references; `readonly` for properties not reassigned after initialization.

* **Minimize Side Effects:** Design pure functions where possible. Make necessary side effects explicit and contained.

**5. Error Handling and Robustness:**

* **Graceful Error Handling:** Implement robust `try...catch` blocks for async operations and potential runtime errors.

* **Custom Error Types:** Define custom error classes for specific application errors, providing context for targeted handling.

* **Type Guards:** Use type guards (`instanceof`, `typeof`, user-defined) to narrow types in conditional blocks, ensuring safety with polymorphic data.

**6. Asynchronous Programming:**

* **Proper Promise Typing:** Always type Promises (e.g., `Promise<MyDataType>`) for correct resolved value typing.

* **Async/Await:** Prefer `async/await` for cleaner, more readable asynchronous code.

**7. Documentation and Readability:**

* **JSDoc for Public APIs:** Document public functions, classes, and interfaces with JSDoc for clear descriptions and IDE support.

* **Meaningful Comments:** Use comments sparingly, focusing on *why* something is done.

* **Code Simplicity:** Strive for the simplest possible solution; avoid over-engineering.

**8. Performance Considerations (Type System):**

* **Avoid Excessive Type Complexity:** Overly complex or deeply nested types can impact TypeScript compilation. Prioritize clarity and maintainability.

* **Type Inference Optimization:** Be aware that large union types or deeply nested conditional types can slow type inference.

**9. Testing:**

* **Unit and Integration Tests:** Write comprehensive tests. Compile-time type safety doesn't replace runtime validation.

* **Test-Driven Development (TDD):** Consider TDD to drive design and ensure testability.

**10. Dependency Management and External Libraries:**

* **Type Definitions:** Ensure all third-party libraries have proper type definitions (`@types/library-name`). Create local `.d.ts` files if needed.

* **Version Control:** Pin dependencies to specific versions to avoid unexpected breaking changes.

Consistently applying these principles leads to robust, type-safe TypeScript code and cultivates a disciplined, senior-level software architect approach.