Literal types let you use exact values as types. Value narrowing helps TypeScript understand what exact value a variable holds, so it can catch mistakes early.
Literal types and value narrowing in Typescript
let direction: 'left' | 'right' | 'up' | 'down'; function move(dir: 'left' | 'right' | 'up' | 'down') { if (dir === 'left') { // do something } else if (dir === 'right') { // do something else } }
Literal types are written as exact values in quotes, like 'left' or 42.
Value narrowing happens when you check a variable's value with if or switch, so TypeScript knows the exact value inside that block.
let answer: 'yes' | 'no'; answer = 'yes'; // OK answer = 'maybe'; // Error: not allowed
function printDirection(dir: 'left' | 'right') { if (dir === 'left') { console.log('Going left'); } else { console.log('Going right'); } }
as const makes the variable a literal type. The switch narrows the value to each case.const status = 'success' as const; function handleStatus(s: 'success' | 'error') { switch (s) { case 'success': console.log('It worked!'); break; case 'error': console.log('There was an error.'); break; } } handleStatus(status);
This program uses a literal type Direction to allow only four directions. The function move checks the exact value and prints a message accordingly.
type Direction = 'north' | 'south' | 'east' | 'west'; function move(direction: Direction) { if (direction === 'north') { console.log('Moving up'); } else if (direction === 'south') { console.log('Moving down'); } else { console.log(`Moving ${direction}`); } } move('north'); move('west');
Literal types help catch errors early by limiting allowed values.
Value narrowing works well with if, else, and switch statements.
Use as const to make variables have literal types instead of general types.
Literal types let you specify exact allowed values for variables.
Value narrowing helps TypeScript understand which exact value a variable has after checks.
Together, they make your code safer and easier to understand.
Practice
Solution
Step 1: Understand the purpose of literal types
Literal types let you restrict a variable to exact values like 'yes' or 10 instead of general types like string or number.Step 2: Compare options with the definition
Only Specify exact allowed values for a variable correctly describes this feature; others describe unrelated concepts.Final Answer:
Specify exact allowed values for a variable -> Option AQuick Check:
Literal types = exact allowed values [OK]
- Confusing literal types with classes
- Thinking literal types disable type checking
- Assuming literal types allow any value
Solution
Step 1: Check the syntax for literal type declaration
To declare a variable with a literal type, you specify the exact value in quotes as the type, like 'open'.Step 2: Evaluate each option
let status: 'open' = 'open'; correctly declares status with type 'open' and assigns 'open'. let status: string = 'open'; uses string type, not literal. let status = 'open'; infers string type but not literal. let status: 'open'; status = 'closed'; declares type 'open' but assigns 'closed', which is invalid.Final Answer:
let status: 'open' = 'open'; -> Option CQuick Check:
Literal type syntax uses exact value in quotes [OK]
- Assigning a different value than the literal type
- Using general types instead of literal types
- Omitting the type and expecting literal type
type Direction = 'left' | 'right';
function move(dir: Direction) {
if (dir === 'left') {
return 'Moving left';
} else {
return 'Moving right';
}
}
console.log(move('right'));Solution
Step 1: Understand the function behavior with literal type
The function move accepts only 'left' or 'right'. It returns 'Moving left' if input is 'left', else 'Moving right'.Step 2: Trace the function call with 'right'
Calling move('right') triggers the else branch, returning 'Moving right'.Final Answer:
Moving right -> Option AQuick Check:
Input 'right' returns 'Moving right' [OK]
- Confusing which branch runs for 'right'
- Expecting compile error for valid literal
- Ignoring else branch
type Status = 'success' | 'error';
function handle(status: Status) {
if (status === 'success') {
console.log('Success!');
} else if (status === 'fail') {
console.log('Failed!');
}
}Solution
Step 1: Check the allowed literal types for Status
Status can only be 'success' or 'error'.Step 2: Analyze the else if condition
The code checks if status === 'fail', which is not part of Status type, causing a type error.Final Answer:
The else if condition checks an invalid literal 'fail' -> Option DQuick Check:
Check conditions must match literal types [OK]
- Using literals not declared in the union type
- Ignoring TypeScript errors on invalid comparisons
- Assuming missing return type causes error here
result after the if statement?type Mode = 'auto' | 'manual';
function setMode(mode: Mode) {
let result: string | undefined;
if (mode === 'auto') {
result = 'Automatic mode set';
} else {
result = undefined;
}
return result;
}Solution
Step 1: Analyze variable declaration and assignments
Variable result is declared as string | undefined. Inside if, assigned string; else assigned undefined.Step 2: Determine narrowed type after if
Since result can be either string or undefined depending on mode, its type remains string | undefined.Final Answer:
string | undefined -> Option BQuick Check:
Variable type includes all assigned values [OK]
- Assuming type narrows to string only
- Ignoring undefined assignment
- Confusing Mode type with result type
Ready to prove it?
Pass the test and this pattern moves unknown
