konrad1221/rules-ts-code-style icon
public
Published on 5/2/2025
konrad1221/rules-ts-code-style

Rules

Control Flow

Early Returns

  • Use early returns to reduce nesting - Handle edge cases first

    const processUser = (user: User | null) => {
      if (!user) return null;
      if (!user.isActive) return null;
      
      return {
        id: user.id,
        name: user.name,
      };
    };
    

No Nested Ternaries

  • Avoid nested ternary operators - Use if statements or early returns

    const getUserDisplay = (user: User) => {
      if (!user.name) return 'Anonymous';
      if (!user.isActive) return 'Inactive User';
      return user.name;
    };
    

No Else-If Chains

  • Use switch statements or lookup objects - Keep conditions flat

    const getStatusColor = (status: Status): string => {
      switch (status) {
        case 'success':
          return 'green';
        case 'warning':
          return 'yellow';
        case 'error':
          return 'red';
        default:
          return 'gray';
      }
    };
    
    // Or using a lookup object
    const statusColors: Record<Status, string> = {
      success: 'green',
      warning: 'yellow',
      error: 'red',
      default: 'gray',
    };
    

Operators and Expressions

Optional Chaining Over &&

  • Use optional chaining for null/undefined checks - Clearer intent and better type safety

    const userName = user?.name;
    const userAddress = user?.address?.street;
    

Function Design

Small Focused Functions

  • Keep functions small and single-purpose - Extract complex logic into helper functions

    const validateUser = (user: User) => {
      if (!isValidName(user.name)) return false;
      if (!isValidEmail(user.email)) return false;
      if (!isValidAge(user.age)) return false;
      return true;
    };
    
    const isValidName = (name: string) => {
      return name.length >= 2 && /^[a-zA-Z\s]*$/.test(name);
    };
    
    const isValidEmail = (email: string) => {
      return /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email);
    };
    
    const isValidAge = (age: number) => {
      return age >= 18 && age <= 120;
    };
    

Naming and Documentation

Clear Variable Names

  • Use descriptive, intention-revealing names - Avoid abbreviations unless common

    const isUserActive = user.status === 'active';
    const hasRequiredPermissions = user.permissions.includes('admin');
    const userDisplayName = user.name || 'Anonymous';
    

Minimal Comments

  • Write self-documenting code - Use comments only for complex business logic

    // Calculate pro-rated amount based on billing cycle
    const calculateProRatedAmount = (amount: number, daysLeft: number, totalDays: number) => {
      return (amount * daysLeft) / totalDays;
    };
    

Error Handling

Proper Error Handling

  • Use try-catch blocks appropriately - Provide meaningful error messages

    const fetchUserData = async (userId: string) => {
      try {
        const response = await api.get(`/users/${userId}`);
        return response.data;
      } catch (error) {
        logger.error('Failed to fetch user data', {
          userId,
          error: error instanceof Error ? error.message : 'Unknown error',
        });
        throw new UserFetchError('Failed to fetch user data');
      }
    };
    

Code Organization

Logical Grouping

  • Group related code together

  • Maintain consistent organization

    class UserService {
      // Properties
      private readonly api: Api;
      private readonly logger: Logger;
    
      // Constructor
      constructor(api: Api, logger: Logger) {
        this.api = api;
        this.logger = logger;
      }
    
      // Public methods
      public async getUser(id: string): Promise<User> {
        // Implementation
      }
    
      public async updateUser(user: User): Promise<User> {
        // Implementation
      }
    
      // Private helpers
      private validateUser(user: User): boolean {
        // Implementation
      }
    }