0
0
Typescriptprogramming~10 mins

Phantom types in Typescript - Step-by-Step Execution

Choose your learning style9 modes available
Concept Flow - Phantom types
Define generic type with phantom parameter
Use phantom type to tag data
Create values with phantom types
Type system enforces distinctions
Prevent mixing incompatible types
Safe code
Phantom types add extra type info that doesn't exist at runtime but helps TypeScript catch errors by distinguishing similar data.
Execution Sample
Typescript
type Phantom<T, PhantomType> = T & { __phantom?: PhantomType };

// Define two phantom types
type USD = { readonly USD: unique symbol };
type EUR = { readonly EUR: unique symbol };

// Create phantom types for money
const priceUSD: Phantom<number, USD> = 10 as Phantom<number, USD>;
const priceEUR: Phantom<number, EUR> = 15 as Phantom<number, EUR>;

// Function only accepts USD
function addUSD(a: Phantom<number, USD>, b: Phantom<number, USD>): Phantom<number, USD> {
  return (a + b) as Phantom<number, USD>;
}
This code uses phantom types to tag numbers as USD or EUR, so TypeScript prevents mixing them accidentally.
Execution Table
StepActionType CheckedResultNotes
1Define Phantom generic typePhantom<T, PhantomType>Type createdPhantom adds phantom type info
2Define USD and EUR phantom typesUSD, EURTypes createdUnique symbols used for tagging
3Create priceUSD as Phantom<number, USD>priceUSDValue 10 tagged as USDTypeScript treats as number with USD tag
4Create priceEUR as Phantom<number, EUR>priceEURValue 15 tagged as EURDifferent phantom tag from USD
5Call addUSD(priceUSD, priceUSD)ValidReturns Phantom<number, USD>Allowed: same phantom type
6Call addUSD(priceUSD, priceEUR)ErrorType errorCannot mix USD and EUR phantom types
7Return from addUSDPhantom<number, USD>Safe USD sumPhantom type ensures safety
💡 Execution stops because mixing different phantom types causes a compile-time error.
Variable Tracker
VariableStartAfter Step 3After Step 4After Step 5Final
priceUSDundefined10 (tagged USD)10 (tagged USD)10 (tagged USD)10 (tagged USD)
priceEURundefinedundefined15 (tagged EUR)15 (tagged EUR)15 (tagged EUR)
addUSD resultundefinedundefinedundefined20 (tagged USD)20 (tagged USD)
Key Moments - 3 Insights
Why can't I add priceUSD and priceEUR even though both are numbers?
Because priceUSD and priceEUR have different phantom types (USD vs EUR), TypeScript treats them as incompatible to prevent mixing currencies. See execution_table step 6.
Does the phantom type exist at runtime?
No, phantom types are only for TypeScript's type system and do not exist in the compiled JavaScript. They help catch errors during development without affecting runtime.
How does the phantom type prevent mixing incompatible types?
The phantom type adds a unique tag to the type signature, so TypeScript sees them as distinct types even if the underlying data is the same. This is shown in execution_table steps 3-6.
Visual Quiz - 3 Questions
Test your understanding
Look at the execution_table at step 6. What happens when you try to add priceUSD and priceEUR?
AThe addition works and returns a number
BTypeScript shows a type error preventing the operation
CThe code runs but logs a warning
DThe phantom types are ignored and addition succeeds
💡 Hint
Check execution_table row 6 where mixing USD and EUR phantom types causes an error.
According to variable_tracker, what is the value of addUSD result after step 5?
A20 tagged as USD
B25 tagged as EUR
CUndefined
D10 tagged as USD
💡 Hint
Look at variable_tracker row for addUSD result after step 5.
If you remove the phantom type from priceUSD, what would happen when adding priceUSD and priceEUR?
ARuntime error would occur
BTypeScript would still prevent adding them
CTypeScript would allow adding them without error
DThe phantom type would be inferred automatically
💡 Hint
Phantom types are what make TypeScript distinguish these values; without them, they are just numbers.
Concept Snapshot
Phantom types in TypeScript:
- Use a generic type with an unused type parameter to tag data.
- Phantom types add compile-time info only, no runtime cost.
- They help distinguish similar data (e.g., currencies) to prevent mixing.
- Example: type Phantom<T, P> = T & { __phantom?: P }.
- TypeScript enforces type safety using phantom tags.
Full Transcript
Phantom types are a way to add extra type information in TypeScript that does not exist at runtime but helps the compiler catch mistakes. We define a generic type that combines a real type with a phantom tag. For example, we tag numbers as USD or EUR using phantom types. When we create values with these tags, TypeScript treats them as different types even though they are both numbers. This prevents us from mixing currencies by mistake. The code example shows defining phantom types, creating tagged values, and a function that only accepts USD tagged numbers. The execution table traces each step: defining types, creating values, and calling the function. It shows that adding two USD values works, but mixing USD and EUR causes a type error. The variable tracker shows how values change with phantom tags. Key moments clarify that phantom types exist only at compile time and prevent mixing incompatible types. The quiz tests understanding of type errors, variable values, and the role of phantom types. The snapshot summarizes phantom types as compile-time tags that improve safety without runtime cost.