Type Aliases in TypeScript Explained

A TypeScript type alias is a name you give to any type. Use the type keyword to create reusable names for object shapes, unions, and tuples, and learn when to choose one over an interface.

5 min read

TypeScript type aliases are names you give to any type. You create one with the type keyword, followed by an identifier, an equals sign, and the type you want to name. After that, you use the alias everywhere you would write the original type.

Defining a type alias for an object

The most common use of a type alias is naming an object shape. The syntax inside the braces is the same as an interface.

typescripttypescript
type Point = {
  x: number;
  y: number;
};
 
function distance(a: Point, b: Point): number {
  return Math.sqrt((b.x - a.x) ** 2 + (b.y - a.y) ** 2);
}
 
console.log(distance({ x: 0, y: 0 }, { x: 3, y: 4 })); // 5

The Point alias names the object shape. The function and variables use Point instead of repeating the inline type. If you later add a z property, you update one line instead of three. Type aliases support the same property modifiers as interfaces: optional with a question mark and readonly with the readonly keyword.

Type aliases can name anything

Unlike interfaces, which only describe object shapes, type aliases can name any TypeScript type. This includes unions, intersections, tuples, function signatures, and even primitives.

A union type alias gives a descriptive name to a set of allowed values:

typescripttypescript
type Status = "loading" | "success" | "error";
 
function handle(status: Status) {
  if (status === "loading") console.log("Waiting...");
  else if (status === "success") console.log("Done.");
  else console.log("Something went wrong.");
}

Status is more descriptive than writing the union inline and can be reused across multiple functions.

A tuple type alias names a fixed-length array with known types at each position. A function signature alias names a callback pattern. And primitive aliases like type UserID = string are valid, but they do not create a truly distinct type -- a UserID is still just a string. If you need actual distinctness, look into branded types.

Combining type aliases with intersections

To compose type aliases, use the ampersand operator for intersections. This is the type alias equivalent of extends on interfaces.

typescripttypescript
type Named = { name: string };
type Aged = { age: number };
 
type Person = Named & Aged & { email: string };
 
const person: Person = {
  name: "Ada",
  age: 30,
  email: "ada@example.com",
};

Person combines Named, Aged, and an inline object with email. The resulting type requires all three properties. If two intersected types have a property with the same name but conflicting types, the resulting property becomes never, meaning no value can satisfy it. For more on conflicts, see interface vs type in TypeScript.

Type aliases cannot be merged

Once a type alias is declared, it is closed. You cannot add new properties in a separate declaration. Trying to redeclare the same type alias name produces a duplicate identifier error.

If you need to augment a type after the fact, use an interface instead. Interfaces support declaration merging, which type aliases do not. This is one of the key differences between the two.

When to use a type alias

Choose a type alias when the type is a union, intersection, tuple, or mapped type -- interfaces cannot describe these. Also use a type alias when you want a short, descriptive name for a complex type, and when the type will not need to be extended or merged.

Choose an interface when describing an object shape that may be extended later, when you want declaration merging support, or when you prefer the clearer error messages that named interfaces provide.

For simple object shapes in your own code, the choice is mostly preference. Pick one style and be consistent. For more on the trade-offs, see interfaces in TypeScript explained.

Common mistakes

Expecting a primitive alias to create a distinct type. type UserID = string is still just string. Assign a raw string to it freely. Use branded types if you need actual distinctness.

Trying to use extends on a type alias. Use the ampersand operator instead. The intersection syntax is the type alias way to compose types.

Trying to redeclare a type alias to add properties. Type aliases are closed. If you need to add properties later, either use an interface or define the full type up front.

Rune AI

Rune AI

Key Insights

  • A type alias is a name for any TypeScript type, created with the type keyword.
  • Type aliases can name object shapes, unions, intersections, tuples, functions, and primitives.
  • Type aliases cannot be reopened or merged; use an interface if you need declaration merging.
  • Use the ampersand operator to combine type aliases, similar to extends on interfaces.
  • For object shapes, interfaces and type aliases are mostly interchangeable -- pick one and be consistent.
RunePowered by Rune AI

Frequently Asked Questions

Can a type alias extend another type alias?

Type aliases cannot use extends like interfaces. Instead, use an intersection: `type Extended = Base & { extra: string }`. This combines the properties of Base with the new ones.

Can I reopen a type alias to add more properties?

No. Once a type alias is declared, it cannot be modified. This is a key difference from interfaces, which support declaration merging. If you need to add properties later, use an interface.

Do type aliases appear by name in error messages?

Since TypeScript 4.2, type alias names may appear in error messages depending on the context. Interfaces always appear by name, which is one reason some teams prefer interfaces for object shapes.

Conclusion

A type alias gives any TypeScript type a reusable name. Use the type keyword followed by an identifier and an equals sign, then any valid type. Type aliases work everywhere interfaces work for object shapes, and they also handle unions, intersections, tuples, and primitive renames that interfaces cannot describe.