Type Aliases
In Module 02 you wrote types inline — string | number, { text: string; answer: string }, 'easy' | 'medium' | 'hard'. Those work, but inline types do not have names. When the same shape appears in three function signatures, you copy it three times. When it changes, you change it in three places.
The type keyword gives any type a name.
The type keyword
Section titled “The type keyword”type Difficulty = 'easy' | 'medium' | 'hard';Now Difficulty is a named type you can use anywhere:
function buildUrl(amount: number, difficulty: Difficulty): string { return `https://opentdb.com/api.php?amount=${amount}&difficulty=${difficulty}`;}
function displayDifficulty(d: Difficulty): void { console.log('Difficulty:', d);}
let level: Difficulty = 'easy';If the allowed values ever change — say, adding 'any' as an option — you update one line in the type declaration and every usage is covered automatically.
Aliasing primitive types
Section titled “Aliasing primitive types”You can alias any type, including primitives:
type Score = number;type QuestionText = string;These are purely for documentation — TypeScript treats Score and number as identical types and does not enforce them separately. For this reason, primitive aliases are uncommon. Use them only when they meaningfully communicate intent to readers of the code.
Aliasing union types
Section titled “Aliasing union types”Union types are where type aliases shine most. Without an alias, a union that appears in multiple places becomes noise:
// Without alias — repeated, fragilefunction start(difficulty: 'easy' | 'medium' | 'hard'): void {}function validate(d: 'easy' | 'medium' | 'hard'): boolean { return true; }With an alias:
type Difficulty = 'easy' | 'medium' | 'hard';
function start(difficulty: Difficulty): void {}function validate(d: Difficulty): boolean { return true; }The intent is named, the constraint is defined once, and both functions stay in sync automatically.
Aliasing object shapes
Section titled “Aliasing object shapes”type can describe object shapes just like an interface (covered in the next lesson). The syntax uses = and a type expression:
type HighScore = { score: number; total: number; date: string;};
const best: HighScore = { score: 8, total: 10, date: 'Jan 15, 2024' };This is equivalent to what you wrote inline in Module 02 — the difference is the name. HighScore can now be imported, reused, and updated in one place.
The ScreenId alias from AceIt
Section titled “The ScreenId alias from AceIt”AceIt’s ui.ts uses a local type alias to constrain the showScreen function’s parameter:
type ScreenId = 'start-screen' | 'loading-screen' | 'question-screen' | 'result-screen';
export function showScreen(id: ScreenId): void { document.querySelectorAll<HTMLElement>('.screen').forEach(el => { el.hidden = true; }); const screen = document.getElementById(id); if (screen) screen.hidden = false;}Without ScreenId, calling showScreen('quiz-screen') — a screen that does not exist — would only fail at runtime. With the alias, it is a compile error. The string 'quiz-screen' is not assignable to ScreenId.
Aliasing complex types
Section titled “Aliasing complex types”type can describe anything — not just objects and unions:
type StringPair = [string, string];type Callback = (score: number, total: number) => void;type NullableQuestion = TriviaQuestion | null;Interfaces (next lesson) can only describe object shapes. type is the only option for tuples, function signatures, union types, and combinations of these.
Exercise
Section titled “Exercise”In types.ts in your aceit/ folder, write the following type aliases:
type Difficulty = 'easy' | 'medium' | 'hard'— you already wrote this; confirm it is exported.type ScreenId = 'start-screen' | 'loading-screen' | 'question-screen' | 'result-screen'.type HighScore = { score: number; total: number; date: string }.type NullableHighScore = HighScore | null— used as the return type forloadHighScore.
type Name = ...gives any type a name — primitives, unions, tuples, object shapes, or function signatures.- Named types make signatures readable and keep related constraints in sync.
typealiases for primitives are purely documentary — TypeScript treats them as identical to the underlying type.typeis the only option for naming unions, tuples, function types, and intersections.- Object shapes can be named with either
typeorinterface— the next lesson covers the difference.