Back to Blog
Lesson 6 of the TypeScript: Typing JavaScript with Confidence course
TypeScriptJuly 17, 20264 min read

Using Type Aliases in TypeScript: A Practical Guide

Learn how to use the Type Alias in TypeScript to define object shapes. Discover the key differences between interfaces and type aliases and when to use each.

TypeScriptType AliasInterfaceObjectsBeginner
Close-up of hands typing on a vintage typewriter, with a warm, nostalgic feel.

Previously in this course, we explored Defining Object Shapes with Interfaces in TypeScript. While interfaces are excellent for defining the structure of objects, TypeScript provides another powerful tool for the job: the Type Alias.

In this lesson, we will define a type alias for a Task, compare it to interfaces, and learn how to decide which tool is best for your specific use case.

Understanding the Type Alias

A type alias creates a name for any valid type—whether it's a primitive, a union, a tuple, or an object shape. Unlike an interface, which is strictly for defining the structure of an object, a type alias is a "label" that points to a type definition.

To define a type alias, use the type keyword followed by the name and an equals sign:

TYPESCRIPT
type TaskID = string | number;

type Task = {
  id: TaskID;
  title: string;
  isCompleted: boolean;
};

This looks remarkably similar to an interface, doesn't it? Let’s look at how they differ and why you might choose one over the other.

Type Alias vs. Interface: The Comparison

White ctrl and A keys on a simple red background create a minimalist and modern look.

While both tools often achieve the same goal, they have distinct behaviors under the hood.

FeatureInterfaceType Alias
Declaration MergingYes (automatic)No
Object ShapesYesYes
Unions/IntersectionsNoYes
ExtensibilityUses extendsUses intersection &

1. Declaration Merging

Interfaces are "open," meaning you can declare the same interface twice, and TypeScript will merge them into one. Type aliases are "closed"—declaring the same name twice will cause a compiler error. This makes interfaces better for library authors who want to allow consumers to extend their types.

2. Unions and Intersections

This is where type aliases shine. If you need to combine two types or create a union (e.g., string | number), you must use a type alias.

TYPESCRIPT
// Valid only with type
type Status = "pending" | "in-progress" | "done";

// Combining types
type User = { name: string };
type Permissions = { role: string };
type Admin = User & Permissions; // Intersection

Worked Example: Updating the Task Client

In our running project, let's update our Task definition to use a type alias. This will allow us to eventually use union types for statuses, which we'll cover later in the course.

TYPESCRIPT
// types.ts
export type Task = {
  id: number;
  title: string;
  isCompleted: boolean;
};

// usage in our API client
function printTask(task: Task) {
  console.log(CE9178">`Task ${task.id}: ${task.title}`);
}

By using type, we keep our options open for future refactoring, such as adding complex union types for task categories or metadata.

Hands-on Exercise

  1. Open your project from the previous lesson.
  2. Replace your interface Task with a type Task.
  3. Create a new type alias called TaskPriority that can be either 'low', 'medium', or 'high'.
  4. Add a priority field to your Task type using your new TaskPriority alias.
  5. Attempt to create a task object and assign it to the Task type to ensure it compiles.

Common Pitfalls

  • Overusing Types: Don't feel pressured to convert every interface to a type. If you are building a standard object-oriented structure or a public API for a library, interface is often more readable and idiomatic.
  • Lost Error Messages: When you use complex intersections (&) in type aliases, TypeScript’s error messages can sometimes be harder to debug than the descriptive messages provided by interfaces.
  • Forgetting Declaration Merging: If you find yourself needing to add properties to a global type across different files, remember that only interface supports this.

Frequently Asked Questions

Q: Should I stop using interfaces entirely? A: No. Interfaces are still the standard for defining object shapes in many production codebases. Use interface for objects and type for unions, intersections, and complex primitives.

Q: Can I extend a type alias? A: You cannot use the extends keyword with a type alias, but you can achieve the same result using intersection types (type C = A & B).

Q: Does it matter for performance? A: Generally, no. Choose based on the features (merging vs. unions) and team preference rather than compiler performance.

Recap

Type aliases provide a flexible way to name any type in TypeScript. While interfaces excel at defining object shapes with declaration merging, type aliases are necessary for union and intersection types. In most cases, you can use either for simple objects, but keep in mind that interface is the go-to for extensible object models.

Up next: Handling Optional Properties — we'll learn how to mark fields as optional to make our Task objects more resilient.

Similar Posts