Search

Command Palette

Search for a command to run...

GitHub Profile
TypeScriptReactPatterns

TypeScript Patterns Every React Developer Should Know

February 28, 2026·5 min read

TypeScript and React are a powerful combination, but getting the most out of both requires knowing the right patterns.

1. Discriminated Unions for Props

Instead of optional props with complex conditional logic:

// ❌ Avoid this
type ButtonProps = {
  variant: "primary" | "secondary";
  icon?: React.ReactNode;
  iconPosition?: "left" | "right";
};

// ✅ Use discriminated unions
type ButtonProps = 
  | { variant: "primary"; icon: React.ReactNode; iconPosition: "left" | "right" }
  | { variant: "secondary"; icon?: never; iconPosition?: never };

2. Polymorphic Components with as Prop

type PolymorphicProps<T extends React.ElementType> = {
  as?: T;
  children: React.ReactNode;
} & React.ComponentPropsWithoutRef<T>;

function Box<T extends React.ElementType = "div">({
  as,
  children,
  ...props
}: PolymorphicProps<T>) {
  const Component = as || "div";
  return <Component {...props}>{children}</Component>;
}

// Usage
<Box as="a" href="/about">Link styled as box</Box>
<Box as="button" onClick={handleClick}>Button box</Box>

3. Const Assertions for Configuration

const ROUTES = {
  home: "/",
  blog: "/blog",
  about: "/about",
} as const;

type Route = (typeof ROUTES)[keyof typeof ROUTES];
// Type: "/" | "/blog" | "/about"

4. Extract Props from Components

type InputProps = React.ComponentProps<"input">;
type ButtonProps = React.ComponentProps<typeof Button>;

5. Generic Components

interface ListProps<T> {
  items: T[];
  renderItem: (item: T) => React.ReactNode;
  keyExtractor: (item: T) => string;
}

function List<T>({ items, renderItem, keyExtractor }: ListProps<T>) {
  return (
    <ul>
      {items.map((item) => (
        <li key={keyExtractor(item)}>{renderItem(item)}</li>
      ))}
    </ul>
  );
}

These patterns will make your React components more robust and your developer experience significantly better. TypeScript isn't just about catching bugs — it's about designing better APIs.