In this article we're going to investigate what is the difference between TypeScript type
and interface
and when to use each one.
TypeScript Type
The Typescript type
keyword is used to define a new type. It can be used to define a type for a primitive, union, tuple, or any other custom type like these:
- String
- Boolean
- Number
- Array
- Tuple
- Enum
- Advanced types
type Person = {
name: string;
age: number;
};
const person: Person = {
name: 'John',
age: 30,
};
TypeScript Interface
The TypeScript interface
keyword is used to define a new type. It can be used to define a type for an object, class, or function.
interface Person {
name: string;
age: number;
}
const person: Person = {
name: 'John',
age: 30,
};
When to Use Them
As you can see from the above examples is that type
and interface
can be used interchangeably in most cases. However, there are some differences between them.
Use type
when you need to define a union, tuple, or any other custom type.
type Status = 'active' | 'inactive';
type Point = [number, number];
Type Intersection
TypeScript allows you to combine multiple types into one using the &
operator. This is called type intersection.
type Person = {
name: string;
};
type Employee = {
job: string;
};
type EmployeePerson = Person & Employee;
const employeePerson: EmployeePerson = {
name: 'John',
job: 'Developer',
};
Type Omits
TypeScript allows you to omit properties from a type using the Omit
utility type.
type Person = {
name: string;
age: number;
job: string;
};
type PersonWithoutJob = Omit<Person, 'job'>;
const personWithoutJob: PersonWithoutJob = {
name: 'John',
age: 30,
};
Type Pick
TypeScript allows you to pick properties from a type using the Pick
utility type.
type Person = {
name: string;
age: number;
job: string;
};
type PersonName = Pick<Person, 'name'>;
const personName: PersonName = {
name: 'John',
};
Type Readonly
TypeScript allows you to make all properties of a type readonly using the Readonly
utility type.
type Person = {
name: string;
age: number;
};
type ReadonlyPerson = Readonly<Person>;
const person: ReadonlyPerson = {
name: 'John',
age: 30,
};
// Error: Cannot assign to 'name' because it is a read-only property.
person.name = 'Jane';
Type Partial
TypeScript allows you to make all properties of a type optional using the Partial
utility type.
type Person = {
name: string;
age: number;
};
type PartialPerson = Partial<Person>;
const person: PartialPerson = {
name: 'John',
};
// Error: Property 'age' is missing in type '{ name: string; }' but required in type 'Person'.
Type Required
TypeScript allows you to make all properties of a type required using the Required
utility type.
type Person = {
name?: string;
age?: number;
};
type RequiredPerson = Required<Person>;
const person: RequiredPerson = {
name: 'John',
age: 30,
};
// Error: Property 'age' is missing in type '{ name: string; }' but required in type 'Person'.
Type Record
TypeScript allows you to create a type with a given set of keys and values using the Record
utility type.
type Person = {
name: string;
age: number;
};
type PersonRecord = Record<string, Person>;
const personRecord: PersonRecord = {
john: {
name: 'John',
age: 30,
},
jane: {
name: 'Jane',
age: 25,
},
};
Type Exclude
TypeScript allows you to exclude properties from a type using the Exclude
utility type.
type Person = {
name: string;
age: number;
job: string;
};
type PersonWithoutJob = Exclude<keyof Person, 'job'>;
const personWithoutJob: PersonWithoutJob = 'name' | 'age';
Type Extract
TypeScript allows you to extract properties from a type using the Extract
utility type.
type Person = {
name: string;
age: number;
job: string;
};
type PersonJob = Extract<keyof Person, 'job'>;
const personJob: PersonJob = 'job';
Type NonNullable
TypeScript allows you to create a type that excludes null
and undefined
from a given type using the NonNullable
utility type.
type Person = {
name: string;
age: number | null;
};
type NonNullablePerson = NonNullable<Person>;
const person: NonNullablePerson = {
name: 'John',
age: 30,
};
// Error: Property 'age' is missing in type '{ name: string; }' but required in type 'Person'.
Interface Extending
Whereas you should use interface when you are defining an object, class, or function. Which means an interface can be used on an object for extending another class.
interface Animal {
name: string;
}
interface Dog extends Animal {
breed: string;
}
class MyDog implements Dog {
name = 'Rex';
breed = 'Labrador';
}
Interface declarations with the same name can be merged, while type declarations with the same name will throw an error.
interface Person {
name: string;
}
interface Person {
age: number;
}
const person: Person = {
name: 'John',
age: 30,
};
Conclusion
In conclusion, use type
when you need to define a union, tuple, or any other custom type. Use interface
when you are defining an object, class, or function.
The default choice you can commonly go for is to use type
in the majority of cases, this is because you have more options as to what can be defined as an type
.