0Pricing
TypeScript Academy · Lesson

Generic Components and forwardRef

Build reusable typed components with generics.

Generic Components and forwardRef is a free TypeScript Academy lesson on CoddyKit — lesson 4 of 4. You can read the complete lesson below for free — then practise it hands-on in the browser with a built-in code editor and a 24/7 AI tutor. It is part of the TypeScript Academy learning path, one of 4 lessons in the course, and your progress syncs across the web and the CoddyKit app.

Welcome

This lesson covers Generic Components And Forwardref in TypeScript with React.

Component Props Interface

Define a props interface for React components to document and enforce the component API.
interface ButtonProps {
  label: string;
  onClick: () => void;
  disabled?: boolean;
}

function Button({ label, onClick, disabled }: ButtonProps) {
  return <button onClick={onClick} disabled={disabled}>{label}</button>;
}

FC vs Explicit Return Type

React.FC adds children and other types automatically. Explicit return type (JSX.Element | null) is often clearer.
const Card: React.FC<{title: string}> = ({ title }) => <div>{title}</div>;

// Or explicit:
function Card2({ title }: { title: string }): JSX.Element {
  return <div>{title}</div>;
}

Typing useState

useState infers the type from the initial value. Provide a type parameter when the initial value is null or ambiguous.
const [count, setCount] = useState(0);           // number
const [name, setName] = useState('');            // string
const [user, setUser] = useState<User | null>(null); // explicit

Typing useReducer

useReducer works best with a discriminated union action type.
type Action = { type: 'increment' } | { type: 'decrement' } | { type: 'reset'; value: number };
function reducer(state: number, action: Action): number {
  switch (action.type) {
    case 'increment': return state + 1;
    case 'decrement': return state - 1;
    case 'reset': return action.value;
  }
}

Typing useRef for DOM

useRef for DOM elements needs a type argument. Initialize with null since the element does not exist yet.
const inputRef = useRef<HTMLInputElement>(null);

// Use:
if (inputRef.current) {
  inputRef.current.focus();
}

Typing Event Handlers

React event types include React.ChangeEvent, React.MouseEvent, and React.FormEvent.
function handleChange(e: React.ChangeEvent<HTMLInputElement>) {
  console.log(e.target.value);
}
function handleClick(e: React.MouseEvent<HTMLButtonElement>) {
  e.preventDefault();
}

Generic Components

Generic components accept a type parameter for flexible, type-safe lists and selects.
function List<T extends { id: number }>({ items }: { items: T[] }) {
  return <ul>{items.map(i => <li key={i.id}>{JSON.stringify(i)}</li>)}</ul>;
}

forwardRef with TypeScript

forwardRef needs type parameters for both the ref element type and props.
const Input = React.forwardRef<HTMLInputElement, InputProps>(
  ({ label, ...props }, ref) => (
    <label>{label}<input {...props} ref={ref} /></label>
  )
);

Custom Hooks Return Types

Type custom hook return values explicitly to avoid any[] inference for tuple returns.
function useToggle(init: boolean): [boolean, () => void] {
  const [state, setState] = useState(init);
  return [state, () => setState(s => !s)];
}

Context with TypeScript

Type React context with a union that includes undefined to force consumers to check for the context.
const AuthContext = React.createContext<User | undefined>(undefined);
function useAuth(): User {
  const ctx = useContext(AuthContext);
  if (!ctx) throw new Error('useAuth must be used within AuthProvider');
  return ctx;
}

Quick Check

What is the correct type for a ref to an HTML input element?

Recap

Type React props with interfaces, useState with type parameters, events with React event types, refs with DOM element generics, and forwardRef with dual type parameters. Generic components enable type-safe reusable UI.

Frequently asked questions

Is the “Generic Components and forwardRef” lesson free?

Yes — the full text of “Generic Components and forwardRef” is free to read here on the web, and the TypeScript Academy course includes 4 lessons in total. To practise it interactively (a built-in code editor and a 24/7 AI tutor) and unlock the rest of the TypeScript Academy course, upgrade to CoddyKit PRO.

What will I learn in “Generic Components and forwardRef”?

Build reusable typed components with generics. You practise TypeScript Academy with hands-on code you run directly in the browser, and a 24/7 AI tutor answers your questions as you work through the lesson.

Do I need any experience to start TypeScript Academy?

No prior experience is required. TypeScript Academy on CoddyKit is structured for beginners through advanced learners; this is — lesson 4 of 4, so you can start here or from the beginning and move at your own pace.

How long does the “Generic Components and forwardRef” lesson take?

Most CoddyKit lessons take about 5–10 minutes. Each one is bite-sized and interactive, so you make steady progress and pick up exactly where you left off across the web and the app.

Can I write and run code in this TypeScript Academy lesson?

Yes. Every TypeScript Academy lesson includes a built-in code editor, so you write and run real code right in your browser and get instant AI feedback — no local setup required.

All lessons in this course

  1. Typing React Component Props
  2. Typing useState and useReducer
  3. Typing useRef and Event Handlers
  4. Generic Components and forwardRef
← Back to TypeScript Academy