TypeScript Interfaces

Describe the shape of an object, including optional properties.

TypeScript
interface Student {
  name: string;
  score: number;
  email?: string;
}

function describe(student: Student): string {
  const contact = student.email ?? "no email";
  return `${student.name}: ${student.score} (${contact})`;
}

const ada: Student = { name: "Ada", score: 91 };
const grace: Student = { name: "Grace", score: 88, email: "grace@example.com" };
console.log(describe(ada));
console.log(describe(grace));
Output
Ada: 91 (no email)
Grace: 88 (grace@example.com)

Explanation

An interface names the shape an object must have: which properties exist and what type each one is. TypeScript checks this structurally, so any object with the right properties fits, with no need to declare that it implements the interface.

A property marked with ? is optional, so its type includes undefined. The nullish coalescing operator ?? supplies a fallback only when the value is null or undefined, which makes it safer than || for values such as 0 or an empty string.

Explore the dry run
Guided walkthroughReady
1interface Student {
2 name: string;
3 score: number;
4 email?: string;
5}
6
7function describe(student: Student): string {
8 const contact = student.email ?? "no email";
9 return `${student.name}: ${student.score} (${contact})`;
10}
11
12const ada: Student = { name: "Ada", score: 91 };
13const grace: Student = { name: "Grace", score: 88, email: "grace@example.com" };
14console.log(describe(ada));
15console.log(describe(grace));

Follow the example

Start to inspect the source, values, and output. These prepared steps explain the published sample; grouped loop steps describe multiple iterations.

View the complete dry-run table
Prepared trace of the published program. Some rows group repeated iterations.
Step / lineWhat happensState after stepOutput so far
Declare the shape: name and score are required, email may be missing.—
—
Use the email if present, otherwise the fallback text.—
—
ada has no email, so the fallback is used.contact = "no email"
Ada: 91 (no email)
grace supplies an email, so it is used.contact = "grace@example.com"
Ada: 91 (no email)
Grace: 88 (grace@example.com)

Cost and common mistakes

Type checking has no runtime cost. The describe call is O(1).

  • Interfaces exist only at compile time. They are erased from the JavaScript, so they cannot validate data that arrives at runtime, such as a JSON response.
  • An optional property can be undefined; read it with ?? or a check before using it as a string.

Try it yourself

Add an optional year: number property and show it in describe.

Reveal answer and reasoning

Add year?: number to Student and format student.year ?? "unknown" in the returned string.

Further reading