Skip to main content

TypeScript Type System & API Standardization

Last Updated: May 2025
Version: 2.0.0
Major Update: API Response Standardization Implementation

Overview

The BuildAppsWith platform implements a comprehensive type system designed to eliminate TypeScript errors, improve developer experience, and ensure consistency across all components and APIs. This system includes standardized component prop interfaces, API response patterns, and centralized enum management.

🎯 Recent Improvements (Version 2.0.0)

API Response Standardization (Sessions 4 & 5)

  • 102+ TypeScript errors resolved through systematic API standardization (23% reduction from 438 → 336)
  • StandardApiResponse pattern implemented across Profile, Marketplace, and Scheduling domains
  • Component compatibility with flattened response structures and consistent data contracts
  • Marketplace alignment following proven patterns established in marketplace domain
  • Error handling with standardized codes, consistent messaging, and predictable structures

Infrastructure Cascade Fixes

  • 51+ errors eliminated through lib/scheduling infrastructure improvements
  • Module export chain fixes - Fixed empty api.ts and utils.ts files causing import failures
  • Type export alignment - Resolved UserRole export chains across 10+ scheduling API files
  • Database schema compatibility - Fixed field mapping and Prisma relation issues

Type System Enhancements

  • Null/undefined normalization in API responses for consistent component consumption
  • ValidationTier enum alignment across marketplace and profile domains
  • Session type compatibility with database property handling (color: string | null)
  • Builder profile response standardization for component integration
  • Decimal number handling - Proper .toNumber() usage in price calculations
  • BuilderSchedulingProfile interface - Complete type definition for scheduling domain

Type System Architecture

Core Type Hierarchy

/lib/types/
├── index.ts              # Central export hub
├── component-types.ts    # Base component interfaces
├── api-types.ts         # API response standardization
├── enums.ts             # Centralized enum definitions
├── prisma-types.ts      # Database type extensions
└── builder.ts           # Legacy type definitions (deprecated)

Domain-Specific Types

/lib/[domain]/types.ts    # Domain-specific type definitions
/components/[domain]/types.ts  # Component-specific interfaces

Component Prop Standardization

Base Component Interfaces

All components extend standardized base interfaces to ensure consistency:
// Base props for all components
export interface BaseComponentProps {
  /** CSS class name */
  className?: string;
  /** Component ID */
  id?: string;
  /** Additional data attributes */
  [key: `data-${string}`]: string | number | boolean | undefined;
}

// Props for components with children
export interface WithChildrenProps {
  children?: ReactNode;
}

// Props for interactive components
export interface DisableableProps {
  disabled?: boolean;
}

export interface LoadableProps {
  loading?: boolean;
  loadingIndicator?: ReactNode;
}

Component Standardization Patterns

1. UI Component Pattern

export interface ButtonProps extends 
  BaseComponentProps,
  DisableableProps,
  Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'className' | 'disabled'> {
  variant?: ButtonVariant;
  size?: ButtonSize;
  fullWidth?: boolean;
}

2. Domain Component Pattern

export interface ProfileHeaderProps extends 
  BaseComponentProps, 
  LoadableProps {
  profile: BuilderProfileData;
  showVerification?: boolean;
  size?: StandardSize;
  editable?: boolean;
}

3. Polymorphic Component Pattern

export type PolymorphicProps<
  C extends ElementType,
  Props = {}
> = Props &
  Omit<ComponentPropsWithoutRef<C>, keyof Props> & {
    as?: C;
  };

Variant and Size Standardization

Standard Size Variants

export type StandardSize = 'xs' | 'sm' | 'md' | 'lg' | 'xl';
export type StandardSpacing = 'none' | 'xs' | 'sm' | 'md' | 'lg' | 'xl' | '2xl';

Implementation Example

const sizeClasses = {
  xs: 'h-8 px-2 py-1 text-xs',
  sm: 'h-8 px-3 text-xs', 
  md: 'h-9 px-4 py-2',
  lg: 'h-10 px-8',
  xl: 'h-12 px-10 text-lg'
};

API Response Standardization

Standardized Response Format

All API responses follow a consistent structure:
export interface StandardApiResponse<T = unknown> {
  success: boolean;
  data?: T;
  error?: ApiError;
  metadata?: ResponseMetadata;
}

export interface ApiError {
  code: string;
  message: string;
  details?: Record<string, unknown>;
}

Domain-Specific Response Types

export interface BuilderProfileResponse extends StandardApiResponse<{
  profile: BuilderProfileData;
  user: UserData;
  permissions: ProfilePermissions;
}> {}

Enum Standardization

Centralized Enum Management

All enums are managed in /lib/types/enums.ts with:
  1. Prisma Re-exports: Standardized naming for database enums
  2. Type Guards: Safe enum validation functions
  3. Utility Functions: String conversion and validation
// Re-export Prisma enums with consistent naming
export { 
  PrismaUserRole as UserRole,
  PrismaBookingStatus as BookingStatus,
  PrismaPaymentStatus as PaymentStatus
};

// Type guards for validation
export function isValidUserRole(role: string): role is PrismaUserRole {
  return Object.values(PrismaUserRole).includes(role as PrismaUserRole);
}

Application-Specific Enums

export enum AuthStatus {
  AUTHENTICATED = 'authenticated',
  UNAUTHENTICATED = 'unauthenticated',
  LOADING = 'loading'
}

export enum ViewMode {
  LIST = 'list',
  GRID = 'grid',
  MAP = 'map'
}

Implementation Guidelines

Component Creation Checklist

When creating new components:
  1. ✅ Extend Base Interfaces: Use BaseComponentProps and relevant mixins
  2. ✅ Define Variants: Create type-safe variant definitions
  3. ✅ Implement Loading States: Add skeleton UI for loading components
  4. ✅ Add Size Variants: Support standard size system
  5. ✅ Include JSDoc: Document all props and their purposes
  6. ✅ Export Types: Re-export types in domain barrel files

Type Safety Best Practices

  1. Strict Prop Interfaces: Never use any in component props
  2. Conditional Classes: Use type-safe conditional styling
  3. Proper State Typing: Define explicit types for component state
  4. Event Handler Typing: Use specific event handler types
// Good: Specific event handler typing
onClick?: (event: React.MouseEvent<HTMLButtonElement>) => void;

// Avoid: Generic any typing
onClick?: (event: any) => void;

Error Reduction Metrics

Current Status (January 2025)

  • Total TypeScript Errors: 421 (down from 442)
  • Component Prop Errors: ~60% reduction achieved
  • API Response Errors: To be addressed in next phase
  • Enum Usage Errors: ~90% reduction achieved

Targeted Error Categories

  1. ✅ RESOLVED: Component prop interface mismatches
  2. ✅ RESOLVED: Enum reference and validation errors
  3. ⏳ IN PROGRESS: API response type standardization
  4. ⏳ PLANNED: Session type property alignment

Migration Guide

Migrating Existing Components

  1. Update Imports: Use centralized type exports
// Old
import { BuilderProfileData } from '@/lib/profile/types';

// New
import { BuilderProfileData } from '@/lib/types';
  1. Extend Base Interfaces: Update component props
// Old
interface ComponentProps {
  className?: string;
  children?: ReactNode;
}

// New
interface ComponentProps extends BaseComponentProps, WithChildrenProps {
  // Additional props
}
  1. Implement Variants: Add standardized variant support
// Add variant props and implementation
variant?: ComponentVariant;
size?: StandardSize;

Component Prop Migration Pattern

// Before: Basic prop interface
interface OldButtonProps {
  className?: string;
  disabled?: boolean;
  onClick?: () => void;
}

// After: Standardized prop interface
interface ButtonProps extends 
  BaseComponentProps,
  DisableableProps,
  Omit<React.ButtonHTMLAttributes<HTMLButtonElement>, 'className' | 'disabled'> {
  variant?: ButtonVariant;
  size?: ButtonSize;
  fullWidth?: boolean;
}

Next Steps

Phase 1 (Current): Foundation Complete ✅

  • Base component type system
  • Core UI component standardization
  • Profile component interfaces

Phase 2 (Next): Domain-Specific Updates

  • BuilderProfileResponse API alignment
  • Session type property fixes
  • Marketplace component standardization

Phase 3 (Future): Full Standardization

  • All remaining components migrated
  • Complete API response standardization
  • Automated type checking in CI/CD

API Response Type Integration

StandardApiResponse Pattern

All API endpoints now follow the StandardApiResponse pattern for consistency:
interface StandardApiResponse<T = unknown> {
  success: boolean;
  data?: T;
  error?: ApiError;
  pagination?: PaginationInfo;
  message?: string;
}

Component Integration Examples

Before API Standardization

// ❌ Inconsistent response handling
const profileData = await fetchProfile(id); // Raw data
if (!profileData) {
  // Unclear error state
}

After API Standardization

// ✅ Standardized response handling
const profileResponse = await getBuilderProfileById(id);
if (!profileResponse.success || !profileResponse.data) {
  console.error('Error:', profileResponse.error?.message);
  return;
}

const profile = profileResponse.data; // Fully typed BuilderProfileData

Type-Safe API Client Pattern

// Client-side API function with standard response
export async function getBuilderProfileById(
  id: string
): Promise<StandardApiResponse<BuilderProfileResponseData>> {
  try {
    const response = await fetch(`/api/profiles/builder/${id}`);
    return await response.json(); // Already in StandardApiResponse format
  } catch (error) {
    return {
      success: false,
      error: {
        code: 'network_error',
        message: error instanceof Error ? error.message : 'Network error'
      }
    };
  }
}

Flattened Response Structure

Builder profile responses are flattened for component compatibility:
// ✅ Flattened structure (no nested user object)
interface BuilderProfileResponseData {
  userId: string;
  email: string;
  name?: string;
  id: string;
  displayName?: string;
  bio?: string;
  avatarUrl?: string;
  topSkills: string[];
  permissions: ProfilePermissions;
  // ... all other fields flattened
}

Type System Error Resolution

The standardization resolved key TypeScript error patterns:

1. Property Access Errors

// ❌ Before: Property 'success' does not exist
if (!profileResponse.success || !profileResponse.data) {

// ✅ After: Full type support with StandardApiResponse
if (!profileResponse.success || !profileResponse.data) {

2. Null/Undefined Property Mismatches

// ❌ Before: Type 'string | null' is not assignable to 'string | undefined'
color: sessionType.color // Database returns null

// ✅ After: Proper null handling in interface
interface SessionType {
  color?: string | null; // Allow both
}

3. Enum Usage Alignment

// ❌ Before: ValidationTier from trust domain (type only)
import { ValidationTier } from '@/lib/trust/types';

// ✅ After: ValidationTier from marketplace domain (enum)
import { ValidationTier } from '@/lib/marketplace/types';
validationTier: ValidationTier.EXPERT // ✅ Works

Implementation Impact

Error Reduction Results

  • Total TypeScript errors reduced: 27+ errors fixed
  • API standardization: 19 errors resolved across profile routes
  • Type alignment: 8 errors resolved in enum and property usage
  • Component compatibility: Consistent data structures across UI

Performance Benefits

  • Type checking speed: Faster builds with consistent types
  • Developer experience: Predictable API response patterns
  • Runtime reliability: Fewer type-related runtime errors
  • Code maintainability: Standardized patterns across codebase

Migration Guidelines

1. API Endpoint Migration

// Before: Inconsistent response format
return NextResponse.json(userData);

// After: Standardized response format  
return NextResponse.json(toStandardResponse(userData));

2. Client Function Migration

// Before: Direct data return
return await response.json();

// After: StandardApiResponse handling
const apiResponse = await response.json();
if (!apiResponse.success) {
  throw new Error(apiResponse.error?.message);
}
return apiResponse.data;

3. Component Migration

// Before: Direct data props
interface ComponentProps {
  profile: any; // Unclear structure
}

// After: Typed response data
interface ComponentProps {
  profile: BuilderProfileResponseData; // Fully typed
}
API Standardization Complete: The type system now includes comprehensive API response standardization, reducing TypeScript errors by 27+ and providing consistent, type-safe interactions across the entire platform.
This type system is designed to be incrementally adopted. Start with new components and gradually migrate existing ones following the patterns outlined above.