Everyday TypeScript: Interfaces
Welcome to the Interfaces lesson!
This lesson is shown as static text below. However, it's designed to be used interactively. Click the button below to start!
We've seen object types like
type User = { name: string }. In this lesson we'll learn about interfaces, which give us another way to define those same types. They also offer some advantages over using thetypekeyword.The next example has
User1andUser2types describing the same object type. We defineUser1as an object type andUser2as an interface. We can assign values of one type to the other with no problems.>
type User1 = {name: string};interface User2 {name: string}const user1: User1 = {name: 'Amir'};const user2: User2 = user1;user2.name;Result:
'Amir'
Why bother with interfaces when we already have object types? One reason is the way that naming conflicts are handled. If we've already defined a type named
Userand we try to define another type with the same name, that's a type error. This matches how other kinds of declarations work, including functions, classes, and variables.>
type User = {name: string};type User = {email: string};Result:
type error: Duplicate identifier 'User'.
We can avoid that error by giving the types separate names. Then we can combine them as an intersection type with
&to get a single object type.>
type HasName = {name: string};type HasEmail = {email: string};type User = HasName & HasEmail;const user: User = {name: 'Amir',email: 'amir@example.com',};user;Result:
Now let's consider the same
Usertype, but defined as an interface. Defining two interfaces with the same name doesn't cause an error. Instead, we get "declaration merging": all interface definitions with the same name are merged into a single interface. It's as if the compiler implicitly intersects them for us.>
interface User {name: string}interface User {admin: boolean}let amir: User = {name: 'Amir',admin: true,};amir;Result:
{name: 'Amir', admin: true}We'll see more features of interfaces in future lessons. For now, here are some reasons to consider using interfaces instead of the
typekeyword:- Interfaces can produce better error messages in some cases.
- Interfaces sometimes compile faster than object types.
- The official TypeScript documentation uses interfaces in its examples, so you'll see a lot of interfaces even if you don't use them.
- The TypeScript team endorses interfaces. For example, Daniel Rosenwasser, TypeScript's Program Manager, has publicly endorsed them over object types: "my take is that it should really just be interfaces for anything that they can model" (source).
You can define many types using either interfaces or the
typekeyword. Neither choice will cause catastrophic problems, so it's a matter of preference. Each team should collectively decide whether they want to favor object types or interfaces.Here's a code problem:
This code example tries to define two types named
User. Change the types into interfaces. Then the code example will work because the interfaces will be merged automatically.(Note that interfaces don't have an
=before the{. This is different from the usual object type syntax,type User = { ... }.)interface User {name: string}interface User {email: string}const user: User = {name: 'Amir',email: 'amir@example.com',};user;- Goal:
{name: 'Amir', email: 'amir@example.com'}- Yours:
{name: 'Amir', email: 'amir@example.com'}