π¦ React with TypeScript β Build Safer & Scalable Apps (2025 Guide)
π§² Introduction β Why Use TypeScript with React?
TypeScript enhances React development by adding static typing, autocomplete, and compile-time error detection. It enables:
- π Safer code through type checking
- π§ Smarter developer tooling and IDE support
- βοΈ Better documentation and component contracts
TypeScript is now the industry standard for large React apps at companies like Microsoft, Meta, and Shopify.
π― In this guide, youβll learn:
- How to set up a React + TypeScript project
- Type your components, props, state, events, and hooks
- Use generics, enums, and utility types
- Best practices and tips for scalable TSX code
βοΈ 1. Setup β Create a React + TypeScript Project
β With Vite (Recommended):
npm create vite@latest my-app -- --template react-ts
β With Create React App (CRA):
npx create-react-app my-app --template typescript
π You’ll get .tsx
support and tsconfig.json
automatically.
π 2. Basic Component Typing
β Functional Component with Props:
type GreetingProps = {
name: string;
age?: number; // optional prop
};
const Greeting: React.FC<GreetingProps> = ({ name, age }) => (
<p>Hello, {name}! {age && `Age: ${age}`}</p>
);
β
Type safety for consumers
β
Autocomplete for props in JSX
π 3. useState & useEffect Typing
const [count, setCount] = useState<number>(0);
const [user, setUser] = useState<User | null>(null);
useEffect(() => {
console.log('Count changed:', count);
}, [count]);
π Always annotate complex types like null
, objects, or arrays
β
Optional: let TypeScript infer types for primitives
π― 4. Typing Events in React
β Input Change Event:
const handleChange = (e: React.ChangeEvent<HTMLInputElement>) => {
setValue(e.target.value);
};
β Form Submit:
const handleSubmit = (e: React.FormEvent<HTMLFormElement>) => {
e.preventDefault();
// submit logic
};
π Use React.*Event
for DOM event types
π§© 5. Children and FC Typing
type CardProps = {
children: React.ReactNode;
};
const Card: React.FC<CardProps> = ({ children }) => (
<div className="card">{children}</div>
);
β
Enables Card
to wrap any nested JSX content
βοΈ 6. Typing useRef and useReducer
β useRef:
const inputRef = useRef<HTMLInputElement>(null);
β useReducer:
type State = { count: number };
type Action = { type: 'increment' | 'decrement' };
const reducer = (state: State, action: Action): State => {
switch (action.type) {
case 'increment': return { count: state.count + 1 };
case 'decrement': return { count: state.count - 1 };
}
};
const [state, dispatch] = useReducer(reducer, { count: 0 });
π Type-safe reducer patterns for complex state logic
π¦ 7. Typing Custom Hooks
function useToggle(initial: boolean): [boolean, () => void] {
const [value, setValue] = useState(initial);
const toggle = () => setValue(v => !v);
return [value, toggle];
}
β
Explicit return types improve reusability
β
Encourages better API design
π 8. TypeScript Utility Types
Utility Type | Description | Example |
---|---|---|
Partial<T> | Makes all properties optional | Partial<User> |
Pick<T, K> | Selects a subset of properties | `Pick<User, ‘name’ |
Omit<T, K> | Excludes properties from type | Omit<User, 'password'> |
Record<K, T> | Creates an object type with keys K | Record<string, boolean> |
Readonly<T> | Makes fields immutable | Readonly<User> |
π Great for forms, settings, feature toggles, etc.
π 9. Best Practices for React + TypeScript
β
Use .tsx
for all components
β
Define Props
types near the component
β
Avoid any
βuse unknown
or strong typing instead
β
Use interface
or type
consistently (prefer type
for components)
β
Type your API responses or use Zod/Yup for runtime validation
β
Use enum
or union
types for fixed values (e.g., button variants)
π Summary β Recap & Next Steps
Using TypeScript with React provides robust typing, better tooling, and fewer bugs in the long run. Itβs ideal for scalable apps, component libraries, and enterprise teams.
π Key Takeaways:
- Type props, state, events, and hooks for full coverage
- Prefer type-safe utilities over loose typing
- Avoid
any
and useinterface
ortype
consistently - Type custom hooks and async APIs for reliability
- Use VS Code and ESLint to maximize productivity
βοΈ Real-World Relevance:
React + TypeScript is used by Meta, Microsoft, Atlassian, and top open-source libraries for their component systems and production codebases.
β FAQ Section
β Should I use interface
or type
for props?
β
Both work. Use type
for function signatures and union types; interface
for extending object shapes.
β How do I type API responses?
β
Use type User = Awaited<ReturnType<typeof fetchUser>>
or tools like Zod
to validate and infer types.
β Is TypeScript required for React?
β No, but it’s highly recommended for better safety, maintainability, and IDE support.
β Can I use React Testing Library with TypeScript?
β
Yes! Most RTL APIs are fully typed. Add @testing-library/jest-dom
for extended matchers.
β How do I type dynamic component props?
β
Use union or discriminated unions for conditional props:
type Props = { type: 'text'; value: string } | { type: 'checkbox'; checked: boolean };
Share Now :