Before You Write Another Line of Code
You’re here because someone threw TypeScript into your React project and now you're knee-deep in red squiggly lines. And then you saw something like interface Foo and type Foo and thought, what’s the damn difference?
This article will set that straight. Just real answers, best practices. You’ll know when to use what, why, and how.
First, What’s the Deal?
Both interface and type let you define the shape of data. like blueprints for your props, state, context, and all the stuff you pass around in React.
interface User {
id: number;
name: string;
}
type Product = {
id: number;
price: number;
}
Looks the same? It mostly is. Until it’s not.
Let’s break it down.
Interfaces: Blueprint Definitions Rooted in Object-Oriented Programming
Interfaces are extendable and play nicely with object-oriented patterns. You’ll want these when you’re building components or models that can be built upon.
// Creating an Employee object
const developer : Employee = {
name: "Alex",
role: "SDE"
}
// Printing an Employee object
function printEmployeeDetails(emp: Employee){
console.log(`${emp.name} is a ${emp.role}`);
}
printEmployeeDetails(developer);// Output: Alex is a SDE
// Creating an Employee array
const team : Employee[] = [
{ name: "Alex", role: "SDE"},
{ name: "Martin", role: "QA"}
]
team.forEach(printEmployeeDetails);// Output: Alex is a SDE, Martin is a QA
Function that accepts both Person and Employee
In the following example, I am passing Employee as an argument, but the funtion onboardNewEmployee() accepts Person as a parameter. However, it still works.
Why?
- We're only accessing the name, which is declared on the Person interface.
- TypeScript sees this as valid because it's fully within the bounds of the Person type.
function onboardNewEmployee(person: Person){// Accepting Person as parameter
console.log(`${person.name}`);
}
const developer : Employee = {
name: "Alex",
role: "SDE"
}
onboardNewEmployee(developer); // Passing employee as an argument
Now, say I change my method body and want to print the role too.
Now, TS gives me an ERROR: Property 'role' does not exist on type 'Person'.
Why?
- The parameter is typed as Person, which only has one property: name: string.
- TypeScript enforces type safety and doesn’t allow access to properties (role) that aren’t declared in the type.
function onboardNewEmployee(person: Person){
console.log(`${person.name} is a ${person.role}`); //ERROR: Property 'role' does not exist on type 'Person'.
}
How do you fix this? Simple use "in" operator.
- 'role' in person checks whether the person object has a role property.
- TypeScript now understands: “Ah! This must be an Employee, not just a Person.”
- You can now safely access the person.role, either directly (if TypeScript is smart enough to infer it), or by asserting: (person as Employee).
function onboardNewEmployee2(person: Person){
if('role' in person){
console.log(`${person.name} is a ${person.role}`); // Alex is a SDE
}
else
{
console.log(`${person.name}`);// King Julien
}
}
interface Person {
name: string;
}
// Creating a Person object
const kj : Person = {
name: "King Julien"
}
interface Employee extends Person {
role: string;
}
// Creating an Employee object
const developer : Employee = {
name: "Alex",
role: "SDE"
}
onboardNewEmployee2(kj);
onboardNewEmployee2(developer);

Join the conversation! Your thoughts help the community grow.