Interfaces and Extensions
Learn how interfaces empower us to define scalable, flexible, and reusable object contracts in TypeScript.
If you’ve been using type
to model object shapes, that’s totally valid. But the interface is often a better choice—one that’s built for scale, collaboration, and evolving codebases.
Interfaces aren’t just a different way to describe object structure. They’re how we model contracts. When we define an interface, we’re saying: “This shape matters. It’s meant to be reused. It’s meant to grow.”
In this lesson, we’ll learn how to declare interfaces, extend them cleanly, and understand exactly how they compare to type
aliases. By the end, we’ll know when and why to reach for each and how to build strong, adaptable types that play well with real-world systems.
Declaring interfaces
Interfaces let us define the shape of an object—its required properties and their types. Just like type aliases, they support optional fields (?
) and readonly
modifiers. And yes, we can use them anywhere we’d use a type: to annotate variables, parameters, return values, and more.
interface User {readonly id: number;username: string;isAdmin: boolean;email?: string;}
Explanation:
Line 1: The
User
interface begins with theinterface
keyword, introducing a reusable named shape.Line 2: The
id
property is marked asreadonly
, meaning it can be set when the object is created but cannot be reassigned later.Line 3:
username
is a required string—this must be present in any object that implementsUser
.Line 4:
isAdmin
is also required and must be a boolean.Line 5:
email
is optional, as indicated by the?
. Objects may include it or leave it out.
If this feels familiar—like something we could do with a type
alias—you’re not wrong. We’ll dig into when and why to choose one over the other later in this lesson. For now, just know this: interfaces are designed for contracts—structures you can extend, share, and evolve confidently across systems and teams.
Interfaces give our code ...