TypeScript Literal Types

Exact values as types

💎 What are Literal Types?

Literal types let you specify exact values a variable can hold, not just general types. Instead of accepting any string or number, you define specific allowed values, creating precise and self-documenting code with compile-time validation.


// String literal type
let direction: "left" | "right";

direction = "left";   // Valid
// direction = "up";  // Error!
                                    

Types of Literals

📝

String Literals

Exact string values

type Status = 
    "active" | 
    "inactive";
🔢

Numeric Literals

Specific numbers only

type DiceRoll = 
    1 | 2 | 3 | 
    4 | 5 | 6;

Boolean Literals

True or false specifically

type AlwaysTrue = true;
type AlwaysFalse = 
    false;
🔗

Combined Literals

Mix different literal types

type Mixed = 
    "yes" | "no" | 
    1 | 0;

🔹 String Literal Types

Restrict strings to specific values:

type Theme = "light" | "dark" | "auto";

let currentTheme: Theme = "light";
console.log(`Current theme: ${currentTheme}`);

currentTheme = "dark";
console.log(`Changed to: ${currentTheme}`);

// currentTheme = "blue"; // Error: not in literal union

function setTheme(theme: Theme) {
    console.log(`Setting theme to ${theme}`);
}

setTheme("auto");

Output:

Current theme: light

Changed to: dark

Setting theme to auto

🔹 Numeric Literal Types

Allow only specific numbers:

type DiceRoll = 1 | 2 | 3 | 4 | 5 | 6;
type HttpSuccessCode = 200 | 201 | 204;

let roll: DiceRoll = 4;
console.log(`You rolled: ${roll}`);

let statusCode: HttpSuccessCode = 201;
console.log(`Status: ${statusCode}`);

// let invalidRoll: DiceRoll = 7; // Error!
// let invalidCode: HttpSuccessCode = 404; // Error!

Output:

You rolled: 4

Status: 201

🔹 Boolean Literal Types

Specify exact boolean values:

type AlwaysTrue = true;
type AlwaysFalse = false;

let isEnabled: AlwaysTrue = true;
// let isEnabled: AlwaysTrue = false; // Error!

let isDisabled: AlwaysFalse = false;
// let isDisabled: AlwaysFalse = true; // Error!

console.log(`Enabled: ${isEnabled}`);
console.log(`Disabled: ${isDisabled}`);

Output:

Enabled: true

Disabled: false

🔹 Mixed Literal Types

Combine different literal types:

type Answer = "yes" | "no" | true | false | 1 | 0;

let response1: Answer = "yes";
let response2: Answer = true;
let response3: Answer = 1;

console.log(`Response 1: ${response1}`);
console.log(`Response 2: ${response2}`);
console.log(`Response 3: ${response3}`);

Output:

Response 1: yes

Response 2: true

Response 3: 1

🔹 Literal Types in Functions

Use literals for function parameters and returns:

type Alignment = "left" | "center" | "right";

function alignText(text: string, align: Alignment): string {
    return `[${align.toUpperCase()}] ${text}`;
}

console.log(alignText("Hello", "left"));
console.log(alignText("World", "center"));
console.log(alignText("TypeScript", "right"));

// alignText("Error", "top"); // Error: "top" not allowed

Output:

[LEFT] Hello

[CENTER] World

[RIGHT] TypeScript

🔹 Literal Types with Objects

Use literals in object properties:

type Button = {
    label: string;
    size: "small" | "medium" | "large";
    variant: "primary" | "secondary" | "danger";
};

let submitButton: Button = {
    label: "Submit",
    size: "medium",
    variant: "primary"
};

let cancelButton: Button = {
    label: "Cancel",
    size: "small",
    variant: "secondary"
};

console.log(`${submitButton.label} button: ${submitButton.size}, ${submitButton.variant}`);
console.log(`${cancelButton.label} button: ${cancelButton.size}, ${cancelButton.variant}`);

Output:

Submit button: medium, primary

Cancel button: small, secondary

🔹 Template Literal Types

Create patterns with template literals:

type Color = "red" | "blue" | "green";
type Shade = "light" | "dark";
type ColorShade = `${Shade}-${Color}`;

let color1: ColorShade = "light-red";
let color2: ColorShade = "dark-blue";
let color3: ColorShade = "light-green";

console.log(color1);
console.log(color2);
console.log(color3);

// let invalid: ColorShade = "medium-red"; // Error!

Output:

light-red

dark-blue

light-green

🔹 Const Assertions

Use 'as const' to create literal types:

// Without const assertion
let status1 = "active"; // Type: string

// With const assertion
let status2 = "active" as const; // Type: "active"

const config = {
    apiUrl: "https://api.example.com",
    timeout: 5000
} as const;

// config.timeout = 3000; // Error: readonly

console.log(`Status: ${status2}`);
console.log(`API: ${config.apiUrl}`);
console.log(`Timeout: ${config.timeout}`);

Output:

Status: active

API: https://api.example.com

Timeout: 5000

🔹 Practical Example

Building a traffic light system with literal types:

type LightColor = "red" | "yellow" | "green";
type LightState = {
    color: LightColor;
    action: "stop" | "slow" | "go";
};

const lights: Record = {
    red: { color: "red", action: "stop" },
    yellow: { color: "yellow", action: "slow" },
    green: { color: "green", action: "go" }
};

function getInstruction(color: LightColor): string {
    const state = lights[color];
    return `Light is ${state.color}: ${state.action.toUpperCase()}!`;
}

console.log(getInstruction("red"));
console.log(getInstruction("yellow"));
console.log(getInstruction("green"));

Output:

Light is red: STOP!

Light is yellow: SLOW!

Light is green: GO!

🧠 Test Your Knowledge

What does a literal type specify?