Skip to content
← Dist
typescript+matchtypescriptmatch

match consumer examples

How a TypeScript app uses @danrabydev/match ^0.3.1: exhaustive Status.match, one ApiResult namespace, peek-then-match, merge, and diagnostics on Error. No _ hatch.

typescriptapp/src/api.ts
import {
  createMatchable,
  peeker,
  type MatchableOf,
} from "@danrabydev/match";

export type User = { id: string; name: string };
export type Post = { id: string; title: string };
export type ApiError = { code: number; message: string };

export const ApiResult = createMatchable({
  Idle: () => ({}),
  Loading: (msg: string) => ({ msg }),
  Success: (data: unknown) => ({ data }),
  Error: (err: unknown) => ({ err }),
  Cached: (at: Date) => ({ at }),
});

export type ApiResult<TData, TErr = unknown> = MatchableOf<
  typeof ApiResult,
  TData,
  TErr
>;

type ApiNs = typeof ApiResult;

const users: Record<string, User> = { "1": { id: "1", name: "ada" } };
const posts: Record<string, Post> = { "9": { id: "9", title: "notes" } };
const cachedAt = new Date("2026-01-01T00:00:00.000Z");

function loadUser(ns: ApiNs, id: string): ApiResult<User, ApiError> {
  if (id === "cached") return ns.Cached(cachedAt);
  if (id === "loading") return ns.Loading("fetching user");
  const found = users[id];
  if (found === undefined) {
    return ns.Error({ code: 404, message: "user not found" });
  }
  return ns.Success(found);
}

export function getUser(id: string): ApiResult<User, ApiError> {
  return loadUser(ApiResult, id);
}

export function getPost(id: string): ApiResult<Post, ApiError> {
  const found = posts[id];
  if (found === undefined) {
    return ApiResult.Error({ code: 404, message: "post not found" });
  }
  return ApiResult.Success(found);
}

export const interceptErrors = peeker("api.errors", {
  Error: ({ err }) => {
    const e = err as ApiError;
    console.error(`${e.code}: ${e.message}`);
  },
});

export class Api {
  private readonly ns = ApiResult.withDiagnostics({
    enabled: true,
    branches: ["Error"],
  });

  getUser(id: string): ApiResult<User, ApiError> {
    const result = loadUser(this.ns, id);
    this.ns.peek(result, interceptErrors);
    return result;
  }
}