A type alias gives a reusable name to a type. It can name an object shape, union, primitive combination, function signature, tuple, generic type, or a type created by composing other types.
Aliases are useful when a type appears in more than one place or when a meaningful name makes the code easier to understand. A good alias should describe a domain idea, not just shorten syntax.
Type aliases are removed during compilation. They help TypeScript check your code, but they do not create runtime JavaScript values.
type UserId = number;
type Status = "draft" | "published" | "archived";
let currentUserId: UserId = 101;
let postStatus: Status = "published";
// postStatus = "deleted"; // Error
A type alias can name an object shape just like an interface. This is common for API responses, form data, component props, service inputs, and view models.
Use readable property names and avoid making one alias responsible for too many different screens or workflows. If a type keeps growing because different features need different fields, split it into smaller aliases.
type Course = {
id: number;
title: string;
lessons: number;
published: boolean;
};
function publish(course: Course): Course {
return { ...course, published: true };
}
const draft: Course = {
id: 1,
title: "TypeScript Type Aliases",
lessons: 8,
published: false,
};
Union aliases are one of the strongest uses for type. A union describes controlled alternatives, such as allowed statuses, roles, button sizes, API result states, or route names.
A union alias gives that set of alternatives a name, which makes function signatures more readable and keeps the same rules consistent across the codebase.
| Alias | Good Use |
|---|---|
UserRole | A fixed set of permissions or access levels. |
ApiStatus | UI state for loading, success, and error flows. |
ButtonSize | A design-system option such as sm, md, or lg. |
type UserRole = "admin" | "editor" | "viewer";
type ApiStatus = "idle" | "loading" | "success" | "error";
function canPublish(role: UserRole): boolean {
return role === "admin" || role === "editor";
}
let status: ApiStatus = "loading";
status = "success";
Function signatures can become noisy when repeated. A type alias gives a callback, handler, formatter, or validator a clear name and keeps function parameters easier to scan.
This is useful in event systems, validation utilities, array helpers, service callbacks, and reusable UI components. The alias should describe the role of the function, not just the shape.
type Validator<T> = (value: T) => string | null;
type Formatter<T> = (value: T) => string;
const required: Validator<string> = (value) => {
return value.trim() === "" ? "Value is required" : null;
};
const money: Formatter<number> = (value) => {
return `Rs. ${value.toFixed(2)}`;
};
console.log(required("TypeScript"));
console.log(money(499));
A tuple is an array with a fixed number of positions and known types at each position. A type alias can make tuple usage clearer, especially with named tuple elements.
Use tuple aliases for small, positional values such as coordinates, status-message pairs, or parser results. If the data has many fields, an object type is usually easier to understand.
type Point = [x: number, y: number];
type SaveResult = [ok: boolean, message: string];
function move(point: Point, dx: number, dy: number): Point {
return [point[0] + dx, point[1] + dy];
}
const result: SaveResult = [true, "Saved successfully"];
Type aliases can compose existing types with intersections. An intersection combines multiple requirements into one type. This is useful when you want to add metadata to a domain model without rewriting all fields.
Do not overuse intersections to create confusing types. If a composed type becomes hard to understand, create a clearer named model with its own fields.
type Timestamped = {
createdAt: string;
updatedAt: string;
};
type BlogPost = {
id: number;
title: string;
};
type BlogPostRecord = BlogPost & Timestamped;
const post: BlogPostRecord = {
id: 1,
title: "Type Aliases",
createdAt: "2026-05-24",
updatedAt: "2026-05-24",
};
Type aliases can accept generic parameters. This lets you describe reusable wrappers such as paginated results, API responses, form state, cache entries, and success/error results.
Generic aliases should preserve useful relationships. For example, ApiResponse<User> says the response data is a user, while ApiResponse<BlogPost[]> says the data is a list of posts.
type ApiResponse<T> = {
data: T;
status: number;
message: string;
};
type Paginated<T> = {
items: T[];
page: number;
totalPages: number;
};
type User = { id: number; name: string };
type UserListResponse = ApiResponse<Paginated<User>>;
Interfaces and type aliases overlap for object shapes, but they are not identical. Interfaces are excellent for object contracts and class implementations. Type aliases are more flexible because they can name unions, primitives, tuples, intersections, mapped types, and conditional types.
In many teams, interfaces are preferred for public object models and aliases are preferred for unions and composed types. The most important rule is consistency within the project.
| Need | Good Choice |
|---|---|
| Object model used by classes | interface |
| Union of allowed values | type |
| Function signature name | type |
| Tuple name | type |
| Public object contract | Either, based on project convention |
Explore 500+ free tutorials across 20+ languages and frameworks.