Frontend Patterns

Pattern

Props Contract

Specify required and optional properties with their expected types.

Props Contract

Problem

Components accept properties without clear contracts, making it unclear which properties are required, optional, or what types they should be. Parent components pass wrong property names, forget required properties, or pass incorrect types, all without compile-time errors. Documentation becomes stale because there’s no single source of truth for component APIs.

Solution

Define explicit types and validation for component props to establish clear interfaces. This documents how to use components and catches mistakes at development time.

Example

This example demonstrates defining a typed interface for component props, making the contract explicit and enabling compile-time validation of prop usage.

// Define the contract for Button props
interface ButtonProps {
  label: string;  // Required prop
  onClick: () => void;  // Required callback
  variant?: 'primary' | 'secondary';  // Optional with specific values
  disabled?: boolean;  // Optional boolean
}

// TypeScript enforces the contract at compile time
function Button({ label, onClick, variant = 'primary', disabled = false }: ButtonProps) {
  return <button onClick={onClick} disabled={disabled}>{label}</button>;
}

Benefits

  • Documents component APIs with self-describing type definitions.
  • Catches prop type errors at compile time with TypeScript.
  • Provides autocomplete and inline documentation in IDEs.
  • Makes refactoring safer by tracking all prop usages.

Tradeoffs

  • Requires TypeScript or PropTypes setup, adding build complexity.
  • Can be verbose for components with many props and complex types.
  • Needs maintenance when component APIs evolve or change.
  • May create friction when prototyping with rapidly changing interfaces.
Stay Updated

Get New Patterns
in Your Inbox

Join thousands of developers receiving weekly insights on frontend architecture patterns

No spam. Unsubscribe anytime.