Back to articles

Mastering TypeScript for React Developers

Essential TypeScript patterns and best practices for React development.

TypeScript and React work well together. A few patterns go a long way in making your components easier to maintain and your codebase easier to refactor. Here’s a focused set of practices that will help you get the most out of both.

Typing Component Props

Define an interface or type for your props and use it with React.FC or, more commonly, a plain function. Prefer interface for object shapes so you can extend them later. Use optional props (?) only when they’re truly optional, and give them sensible defaults inside the component if needed.

Handling Events and Forms

Use React’s built-in event types: React.ChangeEvent<HTMLInputElement>, React.FormEvent<HTMLFormElement>, and so on. For custom inputs, generic types like React.ChangeEvent<HTMLInputElement> keep your handlers type-safe. When you need to pass a handler down, type it as React.MouseEventHandler<HTMLButtonElement> or the appropriate event handler type so children get correct autocomplete and checks.

Typing Hooks and Data

Use generics with useState when the initial value doesn’t tell TypeScript the full type (e.g. useState<User | null>(null)). For useRef, distinguish between refs that hold DOM nodes (useRef<HTMLDivElement>(null)) and refs that hold mutable values. With data from APIs, define a single source of truth (e.g. a User type) and use it for fetch responses, state, and props.

Working with Children and Render Props

Type children as React.ReactNode when you accept any valid React content. For render props, use a function type like (item: T) => React.ReactNode so both the parent and the consumer get proper type checking.

Keeping Types Maintainable

Colocate types with the components or modules that use them, and extract shared types into a types or models folder when multiple features depend on them. Use satisfies or branded types when you need to narrow literals or IDs. Avoid any; use unknown and narrow with type guards when the shape isn’t known upfront.

Conclusion

TypeScript in React is about clarity and safety: props, events, and data get a single definition, and the compiler catches many bugs before they reach the browser. Start with solid prop and event types, then layer in hooks and API types. Once these patterns become habit, you’ll spend less time debugging and more time building.