Types and interfaces both let you describe the shape of an object.
In React, we often use them for declaring props, state, API responses, and config objects.
// Using type
type User = {
id: string;
name: string;
age?: number; // optional
};
// Using interface
interface Product {
id: number;
title: string;
}
When to Use What?
Interface
Use interface when you're working with object-like structures such as props and API response types.
Interfaces can be extended using extends , making it easy to reuse and compose types in a clean, modular way.
interface User {
id: string;
name: string;
age?: number; // Optional
}
// Extend User to include email for registered users
interface RegisteredUser extends User {
email: string;
isVerified: boolean;
}
const guestUser: User = {
id: "guest-01",
name: "Guest"
};
const registeredUser: RegisteredUser = {
id: "user-123",
name: "Alice",
age: 25,
email: "alice@example.com",
isVerified: true
};
💡 React Tip: Prefer interface for component props because they’re extendable.
Type
Use type for unions, primitives, or when combining complex types.
Union Types
type Status = 'loading' | 'success' | 'error'; // union type
const showStatus = (status: Status) : void => {
if (status === 'loading') {
console.log('Please wait...');
}
}
showStatus('loading'); // "Please wait..."
showStatus('success'); // Print nothing
Discriminated Unions (Tagged Unions)
Useful for modeling variants like UI components and API states.
type TextInput = { type: 'text'; placeholder: string };
type CheckboxInput = { type: 'checkbox'; checked: boolean };
// Now the FormInput takes in either TextInput or CheckboxInput
type FormInput = TextInput | CheckboxInput;
const renderInput = (input: FormInput) : JSX.Element => {
// render the input based on the type accordingly
if (input.type === 'text') {
return <input type="text" placeholder={input.placeholder} />;
}
return <input type="checkbox" checked={input.checked} />;
}