Loading lesson path
Literal types in TypeScript allow you to specify exact values that variables can hold, providing more precision than broader types like string or number.
Formula
They are the building blocks for creating precise and type - safe applications.: Exact string values like "success" | "error"
: Specific numbers like 1 | 2 | 3
: Either true or false
: String literal types built using template string syntax
A string literal type represents a specific string value:
// A variable with a string literal type let direction: "north" | "south" | "east" | "west";
// Valid assignments direction = "north";
direction = "south";// Invalid assignments would cause errors
// direction = "northeast"; // Error: Type '"northeast"' is not assignable to type '"north" | "south" | "east" | "west"'
// direction = "up"; // Error: Type '"up"' is not assignable to type '"north" | "south" | "east" | "west"'
// Using string literal types in functions function move(direction: "north" | "south" | "east" | "west") {
console.log(`Moving ${direction}`);
}
move("east"); // Valid
// move("up"); // Error: Argument of type '"up"' is not assignable to parameter of type...Similar to string literals, numeric literal types represent specific numeric values:
// A variable with a numeric literal type let diceRoll: 1 | 2 | 3 | 4 | 5 | 6;
// Valid assignments diceRoll = 1;
diceRoll = 6;// Invalid assignments would cause errors
// diceRoll = 0; // Error: Type '0' is not assignable to type '1 | 2 | 3 | 4 | 5 | 6'
// diceRoll = 7; // Error: Type '7' is not assignable to type '1 | 2 | 3 | 4 | 5 | 6'
// diceRoll = 2.5; // Error: Type '2.5' is not assignable to type '1 | 2 | 3 | 4 | 5 | 6'
// Using numeric literal types in functions function rollDice(): 1 | 2 | 3 | 4 | 5 | 6 {
return Math.floor(Math.random() * 6) + 1 as 1 | 2 | 3 | 4 | 5 | 6;
}
const result = rollDice();
console.log(`You rolled a ${result}`);Boolean literal types are less commonly used since there are only two boolean values, but they can be useful in specific scenarios:
// A type that can only be the literal value 'true'
type YesOnly = true;
// A function that must return true function alwaysSucceed(): true {
// Always returns the literal value 'true'
return true;
}
// Boolean literal combined with other types type SuccessFlag = true | "success" | 1;
type FailureFlag = false | "failure" | 0;
function processResult(result: SuccessFlag | FailureFlag) {
if (result === true || result === "success" || result === 1) {
console.log("Operation succeeded");
} else {
console.log("Operation failed");
}
}
processResult(true); // "Operation succeeded"
processResult("success"); // "Operation succeeded"
processResult(1); // "Operation succeeded"
processResult(false); // "Operation failed"Literal types can be combined with object types to create very specific shapes:
// Object with literal property values type HTTPSuccess = {
status: 200 | 201 | 204;
statusText: "OK" | "Created" | "No Content";
data: any;
};
type HTTPError = {
status: 400 | 401 | 403 | 404 | 500;
statusText: "Bad Request" | "Unauthorized" | "Forbidden" | "Not Found" | "Internal Server Error";
error: string;
};
type HTTPResponse = HTTPSuccess | HTTPError;
function handleResponse(response: HTTPResponse) {
if (response.status >= 200 && response.status < 300) {
console.log(`Success: ${response.statusText}`);
console.log(response.data);
} else {
console.log(`Error ${response.status}: ${response.statusText}`);
console.log(`Message: ${response.error}`);
}
}
// Example usage const successResponse: HTTPSuccess = {
status: 200, statusText: "OK", data: { username: "john_doe", email: "john@example.com" }
};
const errorResponse: HTTPError = {
status: 404, statusText: "Not Found", error: "User not found in database"
};
handleResponse(successResponse);
handleResponse(errorResponse);TypeScript 4.1+ introduced template literal types, which allow you to create new string literal types by combining existing ones using template string syntax:
// Basic template literals type Direction = "north" | "south" | "east" | "west";
type Distance = "1km" | "5km" | "10km";
// Using template literals to combine them type DirectionAndDistance = `${Direction}-${Distance}`;Formula
// "north - 1km" | "north - 5km" | "north - 10km" | "south - 1km" | ...let route: DirectionAndDistance;
route = "north-5km"; // Valid route = "west-10km"; // Valid
// route = "north-2km"; // Error
// route = "5km-north"; // Error
// Advanced string manipulation type EventType = "click" | "hover" | "scroll";
type EventTarget = "button" | "link" | "div";
type EventName = `on${Capitalize<EventType>}${Capitalize<EventTarget>}`;
// "onClickButton" | "onClickLink" | "onClickDiv" | ...
// Dynamic property access type User = {
id: number;
name: string;
email: string;
createdAt: Date;
};
type GetterName<T> = `get${Capitalize<string & keyof T>}`;
type UserGetters = {
[K in keyof User as GetterName<User>]: () => User[K];
};
// { getId: () => number; getName: () => string; ... }Formula
// String pattern matching type ExtractRouteParams < T extends string > =T extends `${string}:${infer Param}/${infer Rest}`Formula
? Param | ExtractRouteParams < Rest >: T extends `${string}:${infer Param}`? Param
: never;
type Params = ExtractRouteParams<"/users/:userId/posts/:postId">; // "userId" | "postId"
// CSS units and values type CssUnit = 'px' | 'em' | 'rem' | '%' | 'vh' | 'vw';
type CssValue = `${number}${CssUnit}`;
let width: CssValue = '100px'; // Valid let height: CssValue = '50%'; // Valid
// let margin: CssValue = '10'; // Error
// let padding: CssValue = '2ex'; // Error
// API versioning type ApiVersion = 'v1' | 'v2' | 'v3';
type Endpoint = 'users' | 'products' | 'orders';
type HttpMethod = 'GET' | 'POST' | 'PUT' | 'DELETE';
type ApiUrl = `https://api.example.com/${ApiVersion}/${Endpoint}`;
// Complex example: Dynamic SQL query builder type Table = 'users' | 'products' | 'orders';Formula
type Column < T extends Table > =T extends 'users' ? 'id' | 'name' | 'email' | 'created_at' : T extends 'products' ? 'id' | 'name' | 'price' | 'in_stock' :
T extends 'orders' ? 'id' | 'user_id' | 'total' | 'status' : never;
type WhereCondition<T extends Table> = {
[K in Column<T>]?: {
equals?: any;
notEquals?: any;
in?: any[];
};
};
function query<T extends Table>(Formula
table: T, where?: WhereCondition < T >): `SELECT * FROM ${T}${string}` {
// Implementation would build the query return `SELECT * FROM ${table}` as const;
}
// Usage const userQuery = query('users', {
name: { equals: 'John' }, created_at: { in: ['2023-01-01', '2023-12-31'] }
});Formula
// Type: "SELECT * FROM users WHERE ..."