Skip to content
beginner Phase 2 · TypeScript Refresher for Angular

Types, Interfaces, and Unions

Describe data shapes so inputs and payloads are checked at compile time.

40m
0 problems
Topic Progress 0%

Interfaces for Data Shapes

Interfaces define the shape of objects. In Angular, they are used to type component inputs, service responses, and configuration objects.

Defining and Using Interfaces

interface User {
  id: number;
  name: string;
  email: string;
  role: 'admin' | 'editor' | 'viewer';
}

interface CreateUserRequest {
  name: string;
  email: string;
  role?: 'admin' | 'editor' | 'viewer';
}

Using Interfaces in Angular Components

import { Component, Input } from '@angular/core';

interface CardData {
  title: string;
  description: string;
  imageUrl?: string;
}

@Component({
  selector: 'app-card',
  template: `
    <div class="card">
      <h3>{{ data.title }}</h3>
      <p>{{ data.description }}</p>
      <img *ngIf="data.imageUrl" [src]="data.imageUrl" [alt]="data.title">
    </div>
  `,
})
export class CardComponent {
  @Input({ required: true }) data!: CardData;
}

Optional and Readonly Properties

interface Config {
  apiUrl: string;           // required
  timeout?: number;         // optional
  readonly retries: number; // cannot be reassigned
}

Interface vs Type Alias

Feature Interface Type Alias
Object shapes Yes Yes
Union types No Yes
Intersection types No Yes
Declaration merging Yes No
Extends Yes Yes (via &)
// Interface — preferred for object shapes
interface ButtonProps {
  label: string;
  disabled?: boolean;
}

// Type alias — needed for unions
type Status = 'idle' | 'loading' | 'success' | 'error';

type Result<T> = { success: true; data: T } | { success: false; error: string };

Union Types and Discriminated Unions

Union types allow a variable to hold one of several types. They are essential for modeling state that can take different shapes.

Basic Union Types

type ID = string | number;

function formatId(id: ID): string {
  return id.toString();
}

Discriminated Unions

A discriminated union uses a common literal property to distinguish between variants:

type ApiState<T> =
  | { status: 'idle' }
  | { status: 'loading' }
  | { status: 'success'; data: T }
  | { status: 'error'; error: string };

function renderState<T>(state: ApiState<T>): string {
  switch (state.status) {
    case 'idle':
      return 'Waiting...';
    case 'loading':
      return 'Loading...';
    case 'success':
      return `Data: ${JSON.stringify(state.data)}`;
    case 'error':
      return `Error: ${state.error}`;
  }
}

Union Types in Angular Templates

@Component({
  selector: 'app-status',
  template: `
    <div [ngSwitch]="status.type">
      <p *ngSwitchCase="'success'">{{ status.message }}</p>
      <p *ngSwitchCase="'error'">{{ status.message }}</p>
      <p *ngSwitchDefault>Unknown status</p>
    </div>
  `,
})
export class StatusComponent {
  @Input() status!: { type: 'success'; message: string } | { type: 'error'; message: string };
}

Type Narrowing

TypeScript narrows union types based on checks:

function process(value: string | number | null) {
  if (value === null) {
    return 'No value';
  }
  // TypeScript knows value is string | number here
  if (typeof value === 'string') {
    return value.toUpperCase(); // narrowed to string
  }
  return value.toFixed(2); // narrowed to number
}

Quiz

1. What is the main difference between an interface and a type alias?

Question 1 options

2. What is a discriminated union?

Question 2 options

3. How do you make a property optional in a TypeScript interface?

Question 3 options

Flashcards

Question

When should you use an interface vs a type alias?

Answer

Use interfaces for object shapes (especially public APIs). Use type aliases for unions, intersections, and mapped types.

Question

What is a discriminated union?

Answer

A union where each member shares a common literal property (like 'status') that TypeScript uses for type narrowing.

Question

How do you type a component input that can be string or number?

Answer

Use a union type: @Input() value!: string | number;

Revision Notes

Key Takeaways

  • 1. Interfaces define object shapes for inputs and payloads
  • 2. Union types model fields that accept multiple shapes
  • 3. Discriminated unions enable safe type narrowing
  • 4. TypeScript catches type errors at compile time

Interview Tips

  • • Explain when to prefer interface over type alias
  • • Be ready to demonstrate discriminated unions for API state
  • • Mention how TypeScript's type system prevents runtime errors

Cheat Sheet

TypeScript Types Cheat Sheet

Interface (object shapes):

interface User {
  id: number;
  name: string;
  email?: string;
  readonly role: string;
}

Union types:

type Status = 'idle' | 'loading' | 'success' | 'error';

Discriminated union:

type ApiState<T> =
  | { status: 'loading' }
  | { status: 'success'; data: T }
  | { status: 'error'; error: string };

Type narrowing:

if (typeof value === 'string') { /* string */ }
if (value === null) { /* null */ }

Continue Learning