TS

Type Aliases

TypeScript · 6 entries

Type Alias Basics

syntax
type Name = Type;
example
type UserId = string;
type Coordinate = { x: number; y: number };
type StringOrNumber = string | number;
type Callback = (data: unknown) => void;

const origin: Coordinate = { x: 0, y: 0 };
const userId: UserId = "usr_9f3a";
output
// Type aliases create a name for any type expression

Note Type aliases and interfaces overlap for object shapes, but type aliases can also name unions, tuples, primitives, and function types. Unlike interfaces, type aliases cannot be re-declared for merging. Use interfaces for object shapes that might be extended; use type aliases for everything else.

Union Types

syntax
type Name = TypeA | TypeB | TypeC;
example
type Status = "pending" | "active" | "archived";
type ApiResponse = SuccessResult | ErrorResult;

interface SuccessResult {
  ok: true;
  data: unknown;
}
interface ErrorResult {
  ok: false;
  errorCode: number;
  message: string;
}

function handleResponse(res: ApiResponse) {
  if (res.ok) {
    console.log(res.data); // narrowed to SuccessResult
  } else {
    console.error(res.message); // narrowed to ErrorResult
  }
}
output
// Union means 'one of these types' — must narrow before accessing specific members

Note You can only access properties common to ALL members of a union without narrowing first. Use a shared discriminant property (like 'ok' above) to let TypeScript narrow automatically in conditionals.

Intersection Types

syntax
type Name = TypeA & TypeB;
example
type WithId = { id: string };
type WithTimestamps = { createdAt: Date; updatedAt: Date };

type UserRecord = WithId & WithTimestamps & {
  email: string;
  displayName: string;
};

const user: UserRecord = {
  id: "usr_001",
  email: "[email protected]",
  displayName: "Dev User",
  createdAt: new Date(),
  updatedAt: new Date(),
};
output
// Intersection combines all properties from all types

Note Intersection means 'all of these combined'. If two types have the same property with incompatible types, the intersected property becomes never (which usually means a mistake). Intersections are great for mixin-style composition.

Literal Types

syntax
type Name = "exactValue" | "anotherValue";
type Name = 0 | 1 | 2;
example
type Direction = "north" | "south" | "east" | "west";
type HttpMethod = "GET" | "POST" | "PUT" | "DELETE" | "PATCH";
type DiceRoll = 1 | 2 | 3 | 4 | 5 | 6;

function move(direction: Direction, steps: number) {
  console.log(`Moving ${direction} by ${steps}`);
}

move("north", 3); // OK
// move("up", 3); // Error: Argument of type '"up"' is not assignable
output
// Literal types restrict a value to an exact set of allowed values

Note Literal types turn strings, numbers, or booleans into specific-value types. Combined with unions, they create powerful enumerations without the overhead of enum. const assertions (as const) automatically infer literal types.

Template Literal Types

syntax
type Name = `prefix${OtherType}suffix`;
example
type EventName = "click" | "scroll" | "resize";
type EventHandler = `on${Capitalize<EventName>}`;
// Result: "onClick" | "onScroll" | "onResize"

type CssUnit = "px" | "em" | "rem" | "%";
type CssValue = `${number}${CssUnit}`;

const width: CssValue = "100px"; // OK
const padding: CssValue = "1.5rem"; // OK
// const bad: CssValue = "big"; // Error
output
// EventHandler = "onClick" | "onScroll" | "onResize"

Note Template literal types construct new string types from combinations. They distribute over unions — every combination is produced. Built-in string manipulation types (Capitalize, Uppercase, Lowercase, Uncapitalize) work inside template literals. Extremely powerful for typing DSLs and API patterns.

Generic Type Aliases

syntax
type Name<T> = { ... };
type Name<T, U = DefaultType> = ...;
example
type ApiResult<T> = {
  data: T;
  status: number;
  timestamp: Date;
};

type Nullable<T> = T | null;
type Pair<A, B = A> = [A, B];

const userResult: ApiResult<{ name: string }> = {
  data: { name: "Priya" },
  status: 200,
  timestamp: new Date(),
};

const point: Pair<number> = [10, 20]; // both number
const labeled: Pair<string, number> = ["x", 42];
output
// Generic aliases accept type parameters just like functions accept value parameters

Note Generic type aliases are essential for building reusable type utilities. Default type parameters (B = A) make common cases convenient while keeping the alias flexible. You can also add constraints with extends.