Bird
Raised Fist0
Typescriptprogramming~5 mins

Phantom types in Typescript - Cheat Sheet & Quick Revision

Choose your learning style10 modes available
Recall & Review
beginner
What is a phantom type in TypeScript?
A phantom type is a type parameter used only at compile time to add extra type safety without affecting the runtime code. It helps catch errors early by distinguishing types that are otherwise similar.
Click to reveal answer
beginner
Why use phantom types instead of regular types?
Phantom types let you add extra compile-time checks without adding runtime overhead. They help prevent mixing incompatible types that look similar but represent different concepts.
Click to reveal answer
intermediate
How do phantom types affect the generated JavaScript code?
Phantom types do not appear in the generated JavaScript code because they are only used by the TypeScript compiler for type checking. They have zero runtime cost.
Click to reveal answer
intermediate
Example: What does this TypeScript code do?
<pre>type Meter = { value: number; _unit: 'meter' };
type Second = { value: number; _unit: 'second' };
function addMeters(a: Meter, b: Meter): Meter {
  return { value: a.value + b.value, _unit: 'meter' };
}</pre>
This code uses phantom types (_unit) to distinguish Meter and Second types. The addMeters function only accepts Meter types, preventing accidental mixing with Second types at compile time.
Click to reveal answer
intermediate
Can phantom types be used with generics in TypeScript?
Yes, phantom types are often used as generic type parameters that do not appear in runtime values but help enforce constraints and improve type safety during compilation.
Click to reveal answer
What is the main purpose of phantom types in TypeScript?
AAdd extra runtime checks
BAdd extra compile-time type safety without runtime cost
CImprove performance of JavaScript code
DGenerate additional JavaScript code
Which of these is true about phantom types?
AThey are erased during compilation
BThey are used to store runtime data
CThey increase the size of the compiled JavaScript
DThey exist only at runtime
How can phantom types help prevent bugs?
ABy running extra tests automatically
BBy optimizing memory usage
CBy enforcing different types for similar data at compile time
DBy logging errors at runtime
In this code snippet, what is '_unit' used for?
type Meter = { value: number; _unit: 'meter' };
ATo store the unit at runtime
BTo calculate values
CTo convert units
DAs a phantom type to distinguish Meter from other types
Can phantom types be used with generic functions?
AYes, to add compile-time constraints without runtime impact
BNo, they only work with concrete types
COnly if the generic is a number
DOnly if the generic is a string
Explain what phantom types are and why they are useful in TypeScript.
Think about types that exist only during checking, not when the program runs.
You got /4 concepts.
    Describe a simple example where phantom types prevent mixing incompatible units like meters and seconds.
    Use a property that marks the unit but is not used at runtime.
    You got /3 concepts.

      Practice

      (1/5)
      1. What is the main purpose of using phantom types in TypeScript?
      easy
      A. To improve performance by removing types
      B. To create new objects at runtime
      C. To add extra type information without affecting runtime data
      D. To allow dynamic typing in TypeScript

      Solution

      1. Step 1: Understand phantom types concept

        Phantom types add extra type information that exists only at compile time and does not affect the actual data or runtime behavior.
      2. Step 2: Compare options with concept

        Only To add extra type information without affecting runtime data correctly states that phantom types add extra type info without changing runtime data. Other options describe unrelated concepts.
      3. Final Answer:

        To add extra type information without affecting runtime data -> Option C
      4. Quick Check:

        Phantom types = extra compile-time info [OK]
      Hint: Phantom types add info only at compile time, no runtime change [OK]
      Common Mistakes:
      • Thinking phantom types create new objects
      • Confusing phantom types with runtime data changes
      • Believing phantom types improve runtime performance
      2. Which of the following is the correct way to declare a phantom type in TypeScript?
      easy
      A. type UserId = string & { readonly __brand: unique symbol }
      B. type UserId = string | number
      C. type UserId = string[]
      D. type UserId = number

      Solution

      1. Step 1: Identify phantom type syntax

        Phantom types use intersection with a unique symbol or branded property to add phantom info without changing the base type.
      2. Step 2: Check each option

        type UserId = string & { readonly __brand: unique symbol } uses intersection with a unique symbol brand, which is the correct phantom type pattern. Others are normal types or unions.
      3. Final Answer:

        type UserId = string & { readonly __brand: unique symbol } -> Option A
      4. Quick Check:

        Phantom type = base type & unique brand [OK]
      Hint: Phantom types use intersection with unique symbol branding [OK]
      Common Mistakes:
      • Using union types instead of intersection for phantom types
      • Declaring phantom types as arrays or simple types
      • Missing the unique symbol branding
      3. What will be the result of this TypeScript code?
      type Meter = number & { readonly __unit: 'meter' };
      function addDistance(a: Meter, b: Meter): Meter {
        return (a + b) as Meter;
      }
      const dist1 = 5 as Meter;
      const dist2 = 10 as Meter;
      const total = addDistance(dist1, dist2);
      console.log(total);
      medium
      A. NaN
      B. 15
      C. Type error at addDistance call
      D. undefined

      Solution

      1. Step 1: Understand phantom type behavior at runtime

        Phantom types exist only at compile time. At runtime, they are just numbers. So adding two numbers works normally.
      2. Step 2: Analyze code output

        dist1 and dist2 are numbers with phantom type. Adding them returns 15, which is logged.
      3. Final Answer:

        15 -> Option B
      4. Quick Check:

        Phantom types don't affect runtime value [OK]
      Hint: Phantom types vanish at runtime; values behave normally [OK]
      Common Mistakes:
      • Expecting type errors at runtime
      • Thinking phantom types change runtime values
      • Confusing phantom types with runtime wrappers
      4. Identify the error in this phantom type usage:
      type UserId = string & { readonly __brand: unique symbol };
      function getUser(id: UserId) {
        return `User: ${id}`;
      }
      const id = 'abc123';
      getUser(id);
      medium
      A. Function getUser should return a number, not string
      B. No error, code runs fine
      C. Unique symbol cannot be used in type intersections
      D. Passing a plain string instead of branded UserId causes a type error

      Solution

      1. Step 1: Check argument type for getUser

        getUser expects a UserId (string with phantom brand). Passing plain string 'abc123' lacks the brand, causing a type error.
      2. Step 2: Validate other options

        Return type is correct, unique symbol usage is valid, and code does not run fine due to type mismatch.
      3. Final Answer:

        Passing a plain string instead of branded UserId causes a type error -> Option D
      4. Quick Check:

        Phantom type mismatch = type error [OK]
      Hint: Phantom types require branded values, not plain base types [OK]
      Common Mistakes:
      • Ignoring phantom brand when passing values
      • Thinking unique symbol is invalid in types
      • Assuming no error when types differ
      5. How can phantom types help prevent mixing different ID types in a TypeScript project?
      Consider these types:
      type UserId = string & { readonly __brand: 'UserId' };
      type ProductId = string & { readonly __brand: 'ProductId' };

      What is the main benefit of this approach?
      hard
      A. It prevents accidentally using a ProductId where a UserId is expected at compile time
      B. It improves runtime performance by optimizing string storage
      C. It automatically converts between UserId and ProductId
      D. It allows mixing IDs freely without errors

      Solution

      1. Step 1: Understand phantom branding for IDs

        Phantom types add unique brands to similar base types (string) to distinguish them at compile time.
      2. Step 2: Identify benefit in type safety

        This branding prevents passing a ProductId where a UserId is expected, catching errors before running code.
      3. Final Answer:

        It prevents accidentally using a ProductId where a UserId is expected at compile time -> Option A
      4. Quick Check:

        Phantom types enforce distinct types safely [OK]
      Hint: Phantom types catch ID mix-ups at compile time [OK]
      Common Mistakes:
      • Thinking phantom types affect runtime performance
      • Assuming automatic conversion between branded types
      • Believing phantom types allow mixing without errors
      Recommended

      Ready to prove it?

      Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

      10 questions~5 mineasy hard