Skip to main content

TypeScript Interfaces

From SCRUM-7 and SCRUM-18: Define TypeScript interfaces

My Learning Notes

Object Types can be defined with {}, type, or interface. With interface, subtypes can be created from other types using extend. One subtype can inherit props from multiple parents, so the amount of boilerplate code is cut down.

Key Insights from Code Review

  • Always use lowercase primitive types (string, not String)
  • Add export keyword from the start when creating shared types
  • Double-check field names against specs (typos happen!)

What is an Interface?

An interface defines the shape of an object - what properties it has and their types.

interface Word {
id: string;
word: string;
definition: string;
userId: string;
categoryId?: string; // Optional property
createdAt: Date;
updatedAt: Date;
}

Interface vs Type

Both can define object shapes, but they handle conflicts differently:

Using extends (Interface)

interface Animal {
name: string;
}

interface Dog extends Animal {
breed: string;
}

// Can extend multiple interfaces
interface Pet extends Animal, Nameable {
owner: string;
}

Using Intersection & (Type)

type Animal = { name: string };
type Dog = Animal & { breed: string };
Key Difference
  • extends shows conflicts as errors (safer!)
  • Intersection & can lead to never type if conflicts arise

Optional Properties

Use ? to mark optional properties. You can also assign default values:

interface Category {
id: string;
name: string;
color: string;
description?: string; // Optional
}

// Usage with default
function createCategory(input: CategoryInput) {
return {
...input,
description: input.description ?? "No description"
};
}

Union Types

When a field can be more than one type, use |:

interface ApiResponse {
status: "success" | "error";
data: Word | null;
code: number | string;
}

Readonly Properties

Use readonly for properties that shouldn't change:

interface User {
readonly id: string; // Can't be changed after creation
name: string; // Can be changed
}

VocabPal Interfaces

Our project uses these key interfaces (from SCRUM-7):

// Word saved by user
interface Word {
id: string;
word: string;
definition: string;
userId: string;
categoryId?: string;
createdAt: Date;
updatedAt: Date;
}

// Category for organizing words
interface Category {
id: string;
name: string;
color: string;
userId: string;
createdAt: Date;
updatedAt: Date;
}

// Input types (for creating new items)
type WordInput = Omit<Word, 'id' | 'createdAt' | 'updatedAt'>;
type CategoryInput = Omit<Category, 'id' | 'createdAt' | 'updatedAt'>;

Modeling API Responses

When working with external APIs, create separate interfaces for nested data:

// Dictionary API response structure
interface Phonetics {
text?: string; // Optional - not always present
audio?: string;
}

interface Definition {
definition: string;
example?: string; // Optional
}

interface Meaning {
partOfSpeech: string;
definitions: Definition[];
}

interface DictionaryApiResponse {
word: string;
phonetics: Phonetics[];
meanings: Meaning[];
}
From Code Review

When working with external APIs, test with a real API call to check which fields are actually optional vs required!

Notes from SCRUM-18

Synced from Jira on 2026-04-04

  • Interface vs Type, extending Interfaces: Object Types can be defined with {}, type or interface. With interface, subtypes can be created from other types using “extend”. 1 subtypes can inherit props from multiple parents, so amount of boilerplate code is cut down.
  • Additionally, combination of types can be made using intersection(&). Different to extend when handling conflict of types. Extended type will flag conflict as error while intersection force to satisfy all types definitions if conflict arises, and can lead to “never” type.
  • Optional properties: when the field can be optional in creating an instance of a typescript object. Mark with “?”. We can assign a default value for that optional properties as well.
  • Union types: when 1 field can be more than 1 type, marked with “|”. For example: number|string

Code Review Feedback

Katie Nguyen (2026-02-02):

[Code Review Feedback]

Great job documenting your learning! Your notes demonstrate solid understanding of the core concepts. You correctly identified that extends shows conflicts as errors while intersection can lead to never type - this is an important distinction. Good understanding of optional properties and union types too.

Tip: When you use interfaces in real code, remember to add the export keyword so other files can import them!

Key Takeaways

  • Use interface for object shapes (can extend)
  • Use type for unions and complex types
  • extends catches conflicts; & may create never
  • Mark optional fields with ?
  • Always export shared interfaces
  • Test APIs to know which fields are optional