npm package discovery and stats viewer.

Discover Tips

  • General search

    [free text search, go nuts!]

  • Package details

    pkg:[package-name]

  • User packages

    @[username]

Sponsor

Optimize Toolset

I’ve always been into building performant and accessible sites, but lately I’ve been taking it extremely seriously. So much so that I’ve been building a tool to help me optimize and monitor the sites that I build to make sure that I’m making an attempt to offer the best experience to those who visit them. If you’re into performant, accessible and SEO friendly sites, you might like it too! You can check it out at Optimize Toolset.

About

Hi, 👋, I’m Ryan Hefner  and I built this site for me, and you! The goal of this site was to provide an easy way for me to check the stats on my npm packages, both for prioritizing issues and updates, and to give me a little kick in the pants to keep up on stuff.

As I was building it, I realized that I was actually using the tool to build the tool, and figured I might as well put this out there and hopefully others will find it to be a fast and useful way to search and browse npm packages as I have.

If you’re interested in other things I’m working on, follow me on Twitter or check out the open source projects I’ve been publishing on GitHub.

I am also working on a Twitter bot for this site to tweet the most popular, newest, random packages from npm. Please follow that account now and it will start sending out packages soon–ish.

Open Software & Tools

This site wouldn’t be possible without the immense generosity and tireless efforts from the people who make contributions to the world and share their work via open source initiatives. Thank you 🙏

© 2026 – Pkg Stats / Ryan Hefner

@jordan-hall/typeguard

v0.1.0

Published

A TypeScript library providing type-safe handling of `Result` types, pattern matching, and robust error handling utilities. Designed to enhance code reliability and readability by leveraging TypeScript's powerful type system.

Readme

@jordan-hall/typeguard

A TypeScript library providing type-safe handling of Result types, pattern matching, and robust error handling utilities. Designed to enhance code reliability and readability by leveraging TypeScript's powerful type system.

Table of Contents

Features

  • Result Types: Simplify error handling by encapsulating success and error states.
  • Pattern Matching: Perform expressive and type-safe pattern matching on Result types.
  • Try/Catch Utilities: Advanced try/catch helpers for synchronous and asynchronous functions with type-safe error management.
  • Type Guards and Predicates: Enhance pattern matching with custom type guards and predicate functions.
  • Flexible Patterns: Supports literal, regex, predicate, object, array, and many patterns.

Installation (coming soon JSR)

You can install @jordan-hall/typeguard via Pacakage Json:


### Using Bun
bun install @jordan-hall/typeguard

### Using npm
npm install @jordan-hall/typeguard

### Using yarn
yarn add @jordan-hall/typeguard

### Using pnpm
pnpm install @jordan-hall/typeguard

You can also use JSR (preferred). For import symbol view on JSR website

### Using Deno
deno add jsr:@jordan-hall/@jordan-hall/typeguard

### Using NPM
npx jsr add @jordanhall/@jordan-hall/typeguard

Usage

Result Types

Result<T, E> represents either a successful computation Ok<T> or a failed computation Err<E>.

import { Ok, Err, Result } from '@jordan-hall/typeguard';

type User = { id: number; name: string };
type ValidationError = { field: string; message: string };

const success: Result<User, ValidationError> = Ok({ id: 1, name: "John Doe" });
const failure: Result<User, ValidationError> = Err({ field: "email", message: "Invalid email format" });

Pattern Matching

Perform pattern matching on Result types for expressive and type-safe error handling.

import { match, when, _, Result } from '@jordan-hall/typeguard';

function getUser(id: number): Result<User, ValidationError> {
  if (id === 0) return Err({ field: "id", message: "Invalid user ID" });
  return Ok({ id, name: "Alice" });
}

const result = getUser(1);

const message = match(result,
  { type: 'Ok', pattern: when(user => user.id > 0), handler: user => `User ID: ${user.id}, Name: ${user.name}` },
  { type: 'Err', pattern: _, handler: error => `Error in field ${error.field}: ${error.message}` }
);

console.log(message); // Output: User ID: 1, Name: Alice

Advanced Pattern Matching

Utilize type guards, predicates, and array patterns for complex matching scenarios.

import { match, when, guard, some, every, _ } from '@jordan-hall/typeguard';

interface Order {
  id: string;
  items: Array<{ name: string; price: number }>;
}

interface OrderError {
  code: string;
  message: string;
}

const processOrder = (order: Order): Result<Order, OrderError> => {
  if (order.items.length === 0) return Err({ code: "NO_ITEMS", message: "Order must contain at least one item" });
  return Ok(order);
};

const orderResult = processOrder({ id: "order123", items: [{ name: "Book", price: 10 }] });

const message = match(orderResult,
  { type: 'Ok', pattern: some(when(item => item.price > 5)), handler: order => `Order ${order.id} has expensive items` },
  { type: 'Err', pattern: { code: "NO_ITEMS" }, handler: error => `Order Error: ${error.message}` },
  { type: 'Ok', pattern: _, handler: order => `Order ${order.id} processed successfully` }
);

console.log(message); // Output: Order order123 has expensive items

Try/Catch Utilities

Simplify error handling with type-safe tryCatch and tryCatchAsync functions.

Synchronous tryCatch

import { tryCatch } from '@jordan-hall/typeguard/tryCatch';

const [error, result] = tryCatch(() => JSON.parse('{"key": "value"}'));

if (result)) {
  console.log("Parsed value:", result);
} else {
  console.error("Parsing error:", error);
}

Asynchronous tryCatchAsync

import { tryCatchAsyn } from '@jordan-hall/typeguard/tryCatch';

async function fetchData(): Promise<string> {
  // Simulate fetching data
  return "data";
}

const [error, data] = await tryCatchAsync(() => fetchData());

if (data) {
  console.log("Fetched data:", data);
} else {
  console.error("Fetching error:", error);
}

Utility Functions

Predicates and Guards

Create custom patterns using predicates and type guards.

import { when, guard, match, _, Result } from '@jordan-hall/typeguard';

interface Admin {
  role: 'admin';
  privileges: string[];
}

type User = { name: string; age: number } | Admin;

const isAdmin: guard<Admin> = (value): value is Admin => (value as Admin).role === 'admin';

const userResult: Result<User, string> = Ok({ name: "Bob", age: 25 });

const userMessage = match(userResult,
  { type: 'Ok', pattern: guard(isAdmin), handler: admin => `Admin with privileges: ${admin.privileges.join(", ")}` },
  { type: 'Ok', pattern: _, handler: user => `User: ${user.name}, Age: ${user.age}` },
  { type: 'Err', pattern: _, handler: error => `Error: ${error}` }
);

console.log(userMessage); // Output: User: Bob, Age: 25

Array Patterns

Match arrays with some or every patterns.

import { some, every, when, match, _ } from '@jordan-hall/typeguard';

type Data = number[];

const data: Data = [1, 2, 3, 4];

const pattern = some(when(n => n > 3));

const matchResult = match(data,
  { type: 'Ok', pattern: pattern, handler: () => "At least one number is greater than 3" },
  { type: 'Ok', pattern: _, handler: () => "No number is greater than 3" }
);

console.log(matchResult); // Output: At least one number is greater than 3

API Reference

Types

  • Result<T, E>
    Represents a computation that can either succeed with a value of type T or fail with an error of type E.

  • Ok<T, E>
    Represents a successful computation containing a value of type T.

  • Err<T, E>
    Represents a failed computation containing an error of type E.

Functions

Ok

Creates an Ok result.

const Ok = <T, E>(value: T): Result<T, E> => ({ _tag: 'Ok', value });

Err

Creates an Err result.

const Err = <T, E>(error: E): Result<T, E> => ({ _tag: 'Err', error });

match

Performs pattern matching on a Result type.

function match<T, E, R>(
  result: Result<T, E>,
  ...cases: Array<MatchCase<T, E, R>>
): R;

tryCatch

Executes a synchronous function with type-safe error handling.

function tryCatch<T, E = Error>(
  fn: () => T,
  acceptableErrors?: (new (...args: any[]) => AcceptableErrors<E>)[]
): [ExtractError<E>, null], [null, T];

tryCatchAsync

Executes an asynchronous function with type-safe error handling.

async function tryCatchAsync<T, E = Error>(
  fn: () => Promise<T>,
  acceptableErrors?: (new (...args: any[]) => AcceptableErrors<E>)[]
): Promise<[ExtractError<E>, null], [null, T]>

when

Creates a predicate pattern.

const when = <T>(predicate: (value: T) => boolean): Predicate<T> => predicate;

guard

Creates a type guard pattern.

const guard = <T>(predicate: (value: unknown) => value is T): Guard<T> => predicate;

some

Creates a pattern that matches if any element in an array matches the given pattern.

const some = <T>(pattern: Pattern<T>): Many<T> => ({
  type: 'some',
  pattern,
});

every

Creates a pattern that matches if all elements in an array match the given pattern.

const every = <T>(pattern: Pattern<T>): Many<T> => ({
  type: 'every',
  pattern,
});

Constants

  • _
    Wildcard pattern that matches any value.

    const _ = Symbol('_');

Examples

1. Type-Based Pattern Matching with Result

import { Ok, Err, Result, match, when } from '@jordan-hall/typeguard';

/**
 * Performs division and returns a Result type.
 * @param a The dividend.
 * @param b The divisor.
 * @returns Ok with the result if successful, Err with an error message if division by zero.
 */
function divide(a: number, b: number): Result<number, string> {
  if (b === 0) return Err("Division by zero");
  return Ok(a / b);
}

const result1 = divide(10, 2);
const result2 = divide(10, 0);

// Handling result1
const message1 = match(result1,
  { type: 'Ok', pattern: when(n => n > 5), handler: (value) => `Success: ${value} is greater than 5` },
  { type: 'Ok', pattern: _, handler: (value) => `Success: ${value}` },
  { type: 'Err', pattern: _, handler: (error) => `Error: ${error}` }
);
console.log(message1); // Output: Success: 5 is greater than 5

// Handling result2
const message2 = match(result2,
  { type: 'Ok', pattern: _, handler: (value) => `Success: ${value}` },
  { type: 'Err', pattern: "Division by zero", handler: (error) => `Caught error: ${error}` },
  { type: 'Err', pattern: _, handler: (error) => `Unhandled error: ${error}` }
);
console.log(message2); // Output: Caught error: Division by zero
import { Ok, Err, Result, match, when } from '@jordan-hall/typeguard';

interface Payment {
  method: "credit_card" | "paypal" | "bank_transfer";
  details: {
    cardNumber?: string;
    paypalId?: string;
    bankAccount?: string;
  };
  amount: number;
}

interface PaymentError {
  code: string;
  message: string;
}

/**
 * Processes a payment and returns a Result type.
 * @param payment The payment to process.
 * @returns Ok with the payment if successful, Err with an error otherwise.
 */
function processPayment(payment: Payment): Result<Payment, PaymentError> {
  if (payment.amount <= 0) {
    return Err({ code: "INVALID_AMOUNT", message: "Amount must be greater than zero" });
  }
  // Assume processing logic here...
  return Ok(payment);
}

const payment: Payment = {
  method: "paypal",
  details: {
    paypalId: "[email protected]"
  },
  amount: 100
};

const paymentResult = processPayment(payment);

const paymentMessage = match(paymentResult,
  // Type-based cases
  { type: 'Ok', pattern: when(p => p.amount >= 100), handler: (p) => `Large payment of \$${p.amount}` },
  { type: 'Ok', pattern: _, handler: (p) => `Payment of \$${p.amount} processed` },
  { type: 'Err', pattern: "INVALID_AMOUNT", handler: (e) => `Error: ${e.message}` },

);

console.log(paymentMessage); // Output: Large payment of $100

5. Error Handling with match

import { Ok, Err, Result, match, when } from '@jordan-hall/typeguard';

interface FileData {
  filename: string;
  content: string;
}

interface FileError {
  code: string;
  message: string;
}

/**
 * Reads a file and returns a Result type.
 * @param filename The name of the file to read.
 * @returns Ok with file data if successful, Err with a FileError otherwise.
 */
function readFile(filename: string): Result<FileData, FileError> {
  if (filename === "") {
    return Err({ code: "INVALID_FILENAME", message: "Filename cannot be empty" });
  }
  // Simulate file reading
  if (filename.endsWith(".txt")) {
    return Ok({ filename, content: "Sample text content." });
  }
  return Err({ code: "UNSUPPORTED_FORMAT", message: "File format not supported" });
}

const fileResult = readFile("data.txt");

const fileMessage = match(fileResult,
  { type: 'Ok', pattern: _, handler: (file) => `File "${file.filename}" loaded with content: ${file.content}` },
  { type: 'Err', pattern: { code: "INVALID_FILENAME" }, handler: (error) => `Error: ${error.message}` },
  { type: 'Err', pattern: { code: "UNSUPPORTED_FORMAT" }, handler: (error) => `Error: ${error.message}` }
);

console.log(fileMessage); // Output: File "data.txt" loaded with content: Sample text content.

6. Using Selector Functions in Path-Based Matching

import { Ok, Err, Result, match, when } from '@jordan-hall/typeguard';

interface Employee {
  name: string;
  department: {
    name: string;
    level: number;
  };
  projects: Array<{ title: string; hours: number }>;
}

interface EmployeeError {
  code: string;
  message: string;
}

/**
 * Retrieves employee data and returns a Result type.
 * @param id The ID of the employee.
 * @returns Ok with employee data if found, Err with an EmployeeError otherwise.
 */
function getEmployee(id: string): Result<Employee, EmployeeError> {
  if (id === "unknown") {
    return Err({ code: "NOT_FOUND", message: "Employee not found" });
  }
  return Ok({
    name: "Carol",
    department: {
      name: "Engineering",
      level: 3
    },
    projects: [
      { title: "Project A", hours: 120 },
      { title: "Project B", hours: 80 }
    ]
  });
}

const employeeResult = getEmployee("emp456");

const employeeMessage = match(employeeResult, 
  { type: 'Ok', pattern: when(employee => employee.department.level >= 3), handler: employee => `Senior ${employee.department.name} member: ${employee.name}` },
  { type: 'Ok', pattern: { projects: some(when(project => project.hours > 100)) }, handler: employee => `${employee.name} is working extensively on projects` },
  { type: 'Ok', pattern: when(employee => employee.projects.length > 5), handler: employee => `${employee.name} is handling multiple projects` },
  { type: 'Err', pattern: _, handler: error => `Error: ${error.message}` }
);

console.log(employeeMessage); // Output: Senior Engineering member: Carol