Stop 07 · TypeScript Across the StackTopics · 2/7

Interfaces & Types

Part of the Full Stack Developer Roadmap

In short

Your User shows up in the database layer, the API, the React profile page and the admin panel. Define its shape once, then derive the variations instead of retyping fields everywhere.

Defining the shape of your data models once and reusing that definition everywhere — your `User` or `Post` type should ideally be defined in exactly one place.

The mascot holds up a master form beside a photocopier making identical copies.

Think of it like this

One master form, photocopied

The college office designs one admission form and photocopies it for every department. If a field is added, they change the master, not 500 copies by hand. Hostel and library forms are built from the same master with a few boxes added or blanked out.

Watch it happen

interface or type?

interface

  • Describes object shapes only
  • Extend with extends
  • Can be reopened and merged

type

  • Any type: unions, tuples, primitives
  • Combine with &
  • Works with Omit, Pick, Partial

Both work for objects. Pick one style for models (many teams use interface), and use type for unions and derived types.

The big ideas

What you need to know

Omit what you don't send

Omit<User, "passwordHash"> gives a PublicUser type that can't accidentally include the hash in a response.

Pick for inputs

A signup form only needs name and email. Pick<User, "name" | "email"> keeps it in sync with the model.

Partial for updates

PATCH bodies send only changed fields. Partial<T> makes every field optional in one go.

Extend, don't copy

interface Admin extends User adds permissions without repeating every User field.

See it in code

Walk through the code

ts
1interface User {2  id: string;3  name: string;4  email: string;5  passwordHash: string;6  createdAt: Date;7}8 9interface Admin extends User {10  permissions: string[];11}12 13type PublicUser = Omit<User, "passwordHash">;  // safe to send to the browser14type SignupInput = Pick<User, "name" | "email"> & { password: string };15type UserUpdate = Partial<Pick<User, "name" | "email">>;16type Role = "student" | "mentor" | "admin";

1/4The full model as the backend sees it, password hash included.

Add a phone field to User and every derived type picks it up where it should.

Save yourself the pain

Common mistakes

Oops

Writing separate UserResponse, UserForm and UserRow interfaces with copied fields.

Do this instead

Keep one base type and derive the others with Omit, Pick and Partial, so they can't drift.

Oops

Returning a User object from an API route typed as PublicUser and assuming the hash is removed.

Do this instead

Types don't delete fields at runtime. Actually build a new object without passwordHash before sending it.

Your mission

Model a course platform

~25 min

Quick check

Which of these needs type and can't be written as an interface?

Go deeper

  1. 1Define an interface for your main data model and use it in both API responses and React props.
  2. 2Practice optional and readonly properties for fields that aren't always present.
  3. 3Learn when `type` and `interface` are interchangeable and when one is preferred.

More topics at this stop

Stuck on this topic? Ask an Insider

Get 1:1 guidance from people who've walked this exact path — on the InsideEdge app.

Download
InsideEdge