Chapter 3 of 13
~13 minInterfaces & Type Aliases
Interfaces and type aliases are TypeScript's two main tools for giving a name to a shape of data, so that functions and variables can reference "a User" or "an ApiResponse" instead of repeating an inline object type everywhere.
Defining Shapes with interface
An `interface` describes the shape an object is expected to have - which properties it must contain and what type each one is. TypeScript uses structural typing, so any object that happens to have all the required properties with compatible types satisfies the interface, regardless of whether it was explicitly declared to implement it.
Try it yourself
A basic interface and a matching objectinterface User {
id: number;
name: string;
email: string;
}
function printUser(user: User): void {
console.log(`${user.name} <${user.email}>`);
}
const u = { id: 1, name: 'Ada', email: 'ada@example.com' };
printUser(u); // OK - u structurally matches User, even though it was never declared "as" User
No output yet. Use console.log() to print values here.
Optional Properties and readonly
A property marked with `?`, like `middleName?: string`, is optional - objects satisfying the interface may omit it entirely, and code reading it must handle the possibility of `undefined`. A property marked `readonly` can be set once (typically at creation) but not reassigned afterward, which the compiler enforces even though `readonly` has no effect on the emitted JavaScript at runtime.
Try it yourself
interface Point {
readonly x: number;
readonly y: number;
label?: string;
}
const p: Point = { x: 10, y: 20 };
console.log(p.label); // undefined - label was optional and omitted
// p.x = 99; // Error: cannot assign to 'x' because it is a read-only property
No output yet. Use console.log() to print values here.
Type Aliases
A `type` alias also gives a name to a shape, using `type Name = { ... }` instead of `interface Name { ... }`. For plain object shapes the two are largely interchangeable, but only `type` can name a union (`type Id = string | number`), a tuple, or a primitive alias - things an `interface` cannot express directly.
Try it yourself
type Id = string | number;
type Coordinates = {
x: number;
y: number;
};
function findById(id: Id): void {
console.log('Looking up:', id);
}
findById(42); // OK
findById('abc123'); // also OK - Id is a union of string and number
No output yet. Use console.log() to print values here.
Extending Interfaces
An interface can extend one or more other interfaces with `extends`, inheriting all of their members and adding its own. This is the standard way to model "an Admin is a User plus some extra fields" without repeating the shared properties. Type aliases achieve a similar effect using intersections (`&`), which is covered alongside union types.
Try it yourself
interface User {
id: number;
name: string;
}
interface Admin extends User {
permissions: string[];
}
const admin: Admin = {
id: 1,
name: 'Grace',
permissions: ['manage-users', 'view-billing'],
};
No output yet. Use console.log() to print values here.
Coding challenge
Define an interface Book with title: string, author: string, an optional isbn?: string, and a readonly publishedYear: number. Then create a Book object and write a function that prints a one-line summary of it.
// Write your solution here
No output yet. Use console.log() to print values here.
Answer every question below to mark this chapter as complete.
Quiz Yourself
Score: 0/51. What does it mean that TypeScript uses "structural typing" for interfaces?
2. What effect does `readonly` have on a property at runtime, in the emitted JavaScript?
3. Which of these can a `type` alias express that a plain `interface` cannot express directly?
4. What is the effect of `interface Admin extends User { permissions: string[] }`?
5. What happens when reading a property declared as optional (`middleName?: string`) that was omitted from an object?