TypeScript Type Aliases
last modified October 15, 2026
A type alias gives a name to a type. It is declared with the
type keyword, followed by the name, an equals sign, and the type.
Aliases make long or repeated types readable, give domain meaning to general
types such as string, and keep definitions in one place, so that
a change to the type is made only once. An alias exists only at compile time;
it produces no JavaScript code.
Basic Type Alias
The simplest alias gives another name to a primitive type.
type Age = number;
type Email = string;
const age: Age = 25;
const email: Email = "alice@example.com";
function isAdult(value: Age): boolean {
return value >= 18;
}
console.log(age, email, isAdult(age));
Age means exactly number: the compiler
treats the two as the same type. The alias documents what the number
represents and makes signatures such as isAdult(value: Age)
easier to understand.
$ npx tsx basic_alias.ts 25 alice@example.com true
Object Type Alias
An alias can describe the shape of an object, including optional and readonly properties.
type User = {
readonly id: number;
name: string;
email?: string;
};
const users: User[] = [
{ id: 1, name: "Alice", email: "alice@example.com" },
{ id: 2, name: "Bob" },
];
for (const user of users) {
console.log(`${user.id}: ${user.name} <${user.email ?? "no e-mail"}>`);
}
Every User must have an id and a
name; the email is optional, so its type inside the
loop is string | undefined. The readonly modifier
prevents changing the id after the object is created. For object
shapes, an interface is an equivalent alternative.
$ npx tsx object_alias.ts 1: Alice <alice@example.com> 2: Bob <no e-mail>
Union Type Alias
Aliases are especially useful for union types, which would be tedious to repeat.
type Id = string | number;
function normalize(id: Id): string {
return typeof id === "number" ? `#${id.toString().padStart(5, "0")}` : id.toUpperCase();
}
const ids: Id[] = [42, "ab-17", 1003];
console.log(ids.map(normalize));
The Id alias is used for a parameter and for the
element type of an array. Inside normalize, a
typeof check narrows the union, so that number and string
methods can be used in the right branches.
$ npx tsx union_alias.ts [ '#00042', 'AB-17', '#01003' ]
Literal Type Alias
A union of literal types restricts a value to a fixed set of options.
type Theme = "light" | "dark" | "system";
type Size = 8 | 16 | 24;
function applyTheme(theme: Theme, fontSize: Size): string {
return `theme ${theme}, font ${fontSize}px`;
}
console.log(applyTheme("dark", 16));
// applyTheme("blue", 12); // Error: '"blue"' is not assignable to parameter of type 'Theme'
Only the listed values are accepted. The alias is the single place where the options are defined, and editors offer them as completions.
$ npx tsx literal_alias.ts theme dark, font 16px
Function Type Alias
An alias can name a function type, which is convenient for callbacks.
type Comparator<T> = (a: T, b: T) => number; type Predicate = (value: number) => boolean; const byLength: Comparator<string> = (a, b) => a.length - b.length; const isEven: Predicate = value => value % 2 === 0; console.log(["banana", "fig", "apple"].sort(byLength)); console.log([1, 2, 3, 4, 5, 6].filter(isEven));
The arrow functions have no parameter annotations; their types come
from the aliases, so a and b are strings and
value is a number. Comparator<T> is a generic
alias: its type parameter is filled in where it is used.
$ npx tsx function_alias.ts [ 'fig', 'apple', 'banana' ] [ 2, 4, 6 ]
Tuple Type Alias
An alias can name a tuple, an array with a fixed number of typed elements.
type Point = [x: number, y: number];
type Rgb = [red: number, green: number, blue: number];
function distance([x1, y1]: Point, [x2, y2]: Point): number {
return Math.hypot(x2 - x1, y2 - y1);
}
const toHex = (rgb: Rgb): string =>
"#" + rgb.map(c => c.toString(16).padStart(2, "0")).join("");
console.log(distance([0, 0], [3, 4]));
console.log(toHex([255, 128, 0]));
The labels x and y document the meaning of
the positions. The function parameters destructure the tuples directly. See
the tuples tutorial.
$ npx tsx tuple_alias.ts 5 #ff8000
Combining Type Aliases
Aliases can be built from other aliases, with unions and with intersections.
type Id = string | number;
type Timestamps = {
createdAt: Date;
updatedAt: Date;
};
type Entity = { id: Id } & Timestamps;
type Product = Entity & {
name: string;
price: number;
};
const product: Product = {
id: 1,
name: "Keyboard",
price: 45,
createdAt: new Date(2026, 0, 10),
updatedAt: new Date(2026, 9, 15),
};
console.log(product.name, product.id, product.updatedAt.getFullYear());
The & operator combines object types into one that
has all their properties. Product therefore has an
id, both timestamps, a name, and a price. Small aliases such as
Timestamps can be reused for many entity types.
$ npx tsx combining_aliases.ts Keyboard 1 2026
An Alias Is Not a New Type
Because an alias is only another name, two aliases of the same type are interchangeable.
type UserId = string;
type OrderId = string;
function cancelOrder(orderId: OrderId): string {
return `order ${orderId} cancelled`;
}
const userId: UserId = "user-42";
console.log(cancelOrder(userId));
Passing a user ID where an order ID is expected compiles without
any warning, because both are just string. The aliases document
the intent, but they do not enforce it.
$ npx tsx aliases_structural.ts order user-42 cancelled
Branded Types
To make such types incompatible, a common pattern adds a compile-time brand to the type.
type UserId = string & { readonly __brand: "UserId" };
type OrderId = string & { readonly __brand: "OrderId" };
const toUserId = (value: string) => value as UserId;
const toOrderId = (value: string) => value as OrderId;
function cancelOrder(orderId: OrderId): string {
return `order ${orderId} cancelled`;
}
const orderId = toOrderId("order-7");
console.log(cancelOrder(orderId));
console.log(typeof orderId, orderId.toUpperCase());
The intersection with an object that has a __brand
property makes UserId and OrderId different types.
The brand exists only for the compiler; at runtime, the values are plain
strings, as typeof shows, and all string methods remain
available. The small conversion functions are the only places where a
string becomes an ID, which is a good spot for validation.
$ npx tsx branded.ts order order-7 cancelled string ORDER-7
type UserId = string & { readonly __brand: "UserId" };
type OrderId = string & { readonly __brand: "OrderId" };
function cancelOrder(orderId: OrderId): void {}
const userId = "user-42" as UserId;
cancelOrder(userId);
cancelOrder("order-7");
Now both mistakes are reported: a user ID is not an order ID, and a plain string must go through the conversion first.
$ npx tsc --noEmit
branded_error.ts(8,13): error TS2345: Argument of type 'UserId' is not assignable to parameter of type 'OrderId'.
Type 'UserId' is not assignable to type '{ readonly __brand: "OrderId"; }'.
Types of property '__brand' are incompatible.
Type '"UserId"' is not assignable to type '"OrderId"'.
branded_error.ts(9,13): error TS2345: Argument of type 'string' is not assignable to parameter of type 'OrderId'.
Type 'string' is not assignable to type '{ readonly __brand: "OrderId"; }'.
Aliases from Values
With the typeof type operator, an alias can be derived
from an existing value instead of being written by hand.
const defaultSettings = {
language: "en",
notifications: true,
pageSize: 20,
};
type Settings = typeof defaultSettings;
type SettingKey = keyof Settings;
function update(settings: Settings, key: SettingKey, value: string): Settings {
const current = settings[key];
const parsed = typeof current === "number" ? Number(value)
: typeof current === "boolean" ? value === "true"
: value;
return { ...settings, [key]: parsed };
}
console.log(update(defaultSettings, "pageSize", "50"));
Settings is
{ language: string; notifications: boolean; pageSize: number },
and SettingKey is the union of its keys. When a new setting is
added to defaultSettings, both aliases follow automatically. The
update function converts the string value according to the type
of the current setting.
$ npx tsx typeof_alias.ts
{ language: 'en', notifications: true, pageSize: 50 }
Best Practices
- Name Repeated Types: Give an alias to any union, function, or object type that appears more than once.
- Use Domain Names: Names such as
EmailorPricedocument what a value means. - Remember Aliases Are Transparent: They do not prevent mixing values of the same underlying type; use branded types when that matters.
- Derive Instead of Repeating: Use
typeofandkeyofto build aliases from existing values. - Keep Aliases Small and Composable: Combine focused aliases with
&and|rather than writing large ones.
Source
TypeScript Handbook: Type Aliases
This tutorial covered the basics of type aliases. The type keyword tutorial continues with the differences from interfaces and with generic and recursive aliases.
Author
List all TypeScript tutorials.