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

defered-branch

v2.2.5

Published

Sometimes we need to judge something with multiple cases, but the main job should be done later. So we have Defered Branch!

Downloads

37

Readme

Defered Branch 🌿

A lightweight library providing a if-else like branch, but with deferred execution. You can evaluate conditions now and execute the matched branch later.

For more awesome packages, check out my homepage💛

Features

  • 🎯 Four Execution Patterns: Single/all-match × immediate/dynamic logic
  • 🔒 Type Safe: Full TypeScript support with type inference
  • 🪶 Lightweight: Zero dependencies, minimal footprint
  • 🧩 Flexible: Works with any function signature
  • 📦 Generic: Customizable branch, condition, and nomatch handler types

Change Log

  • 2.2.1-2.2.5

    • Fix: Clear matched branch after execution to prevent stale state issues.
    • Add index to this document.
      • Fixing anchors for npm many times 💢
  • 2.2.0

    • Add deferedBranchAll and deferedBranchAllDynamic for multi-match scenarios.
    • Fix documentation typos.

Installation

npm install defered-branch
# or
pnpm add defered-branch

Overview

deferedBranch - Single-Match Immediate 🏃‍♂️

Evaluate conditions once, execute first match immediately.

Use cases: One-time conditional flows, static condition evaluation

deferedBranchDynamic - Single-Match Reusable 🔄

Reusable branching logic, execute first match dynamically.

Use cases: Event handlers with varying states, repeated conditional logic

deferedBranchAll - Multi-Match Immediate 🎯

Evaluate conditions once, execute all matches immediately.

Use cases: Notification systems, validation rules, multiple event listeners

deferedBranchAllDynamic - Multi-Match Reusable 🌊

Reusable branching logic, execute all matches dynamically.

Use cases: Plugin systems, middleware chains, observer patterns

Usage Examples

Basic deferedBranch

const calculator = deferedBranch<(a: number, b: number) => number>();

calculator
  .add(operation === 'add', (a, b) => a + b)
  .add(operation === 'multiply', (a, b) => a * b)
  .add(operation === 'divide', (a, b) => a / b)
  .nomatch(() => {
    throw new Error('Unknown operation');
  });

const result = calculator.run(10, 5); // Returns calculated result

Reusable Logic with deferedBranchDynamic

import { deferedBranchDynamic } from 'defered-branch';

// Steps to use:
// 1. Create instance
const statusHandler = deferedBranchDynamic<(message: string) => void>();

// 2. Add predicate-based branches
statusHandler
  .add(
    () => server.status === 'online',
    (msg) => logger.info(`✅ ${msg}`)
  )
  .add(
    () => server.status === 'maintenance',
    (msg) => logger.warn(`⚠️ ${msg}`)
  )
  .add(
    () => server.status === 'offline',
    (msg) => logger.error(`❌ ${msg}`)
  );

// 3. Add fallback handler
statusHandler.nomatch((msg) => logger.debug(`🤔 Unknown status: ${msg}`));

// 4. Use repeatedly with different conditions
statusHandler.predicate(); // Evaluates current server.status
statusHandler.run('Server health check completed');

// Later, when server.status changes...
statusHandler.predicate(); // Re-evaluates with new status
statusHandler.run('Status updated');

deferedBranchAll for Multi-Match Execution

Same as deferedBranch

deferedBranchAllDynamic

Same as deferedBranchDynamic

Real-world Example

Theme Switching

const themeHandler = deferedBranchDynamic<() => void>();

themeHandler
  .add(
    () => preferences.theme === 'dark',
    () => applyDarkTheme()
  )
  .add(
    () => preferences.theme === 'light',
    () => applyLightTheme()
  )
  .add(
    () => preferences.theme === 'auto',
    () => applySystemTheme()
  )
  .nomatch(() => {
    // usually handles parameter validations
    throw new TypeError('Invalid theme preference');
  });

// Reuse whenever preferences change
function onConfigChange() {
  themeHandler.predicate();
  xxxHandler.predicate();
  yyyHandler.predicate();

  // some other logic...create some objects..
  // some other logic...run some funtions...

  themeHandler.run();
  xxxHandler.run();
  yyyHandler.run();
}

h function

This is a simplied example from package KT.js

In this section, we can see that element creation separates judgement and dealing of attr and content. With out this package, we should judge 2 times and the code would be too long for one .ts file.

const attrBranch = deferedBranchDynamic<BranchFn, NoMatchFn, PredicateFn>()
  .add((_, attr) => typeof attr === 'string', attrIsString)
  .add((_, attr) => typeof attr === 'object' && attr !== null, attrIsObject)
  .nomatch(invalidAttrHandler);
const contentBranch = __Same_As_AttrBranch__;

function h<T extends HTMLTag>(
  tag: T,
  attr: RawAttribute = '',
  content: RawContent = ''
): HTMLElement<T> {
  if (typeof tag !== 'string') {
    throw new TypeError('[__NAME__:h] tagName must be a string.');
  }
  attrBranch.predicate(null, attr);
  contentBranch.predicate(null, content);

  // create element
  const el = document.createElement(tag) as HTMLElement<T>;
  // ... some element enhancement logic ...

  attrBranch.run(element, attr);
  contentBranch.run(element, content);

  // ... other logic ...
}

API Reference

deferedBranch()

Creates a new deferred branch instance for immediate execution scenarios.

Methods

.add(condition: boolean, branch: Function): DeferBranch
  • Adds a conditional branch that executes if condition is true
  • First-match wins: the first truthy branch will be selected; later entries are ignored
  • Returns the instance for chaining
.nomatch(handler: Function): DeferBranch
  • Sets an immediate fallback handler
  • Executes instantly if no previous branch matched
  • Ignores later matched branches
.run(...args): any
  • Executes the matched branch or fallback handler
  • Passes arguments to the executed function
  • Returns the function's return value or undefined

deferedBranchDynamic()

Creates a new dynamic deferred branch instance for reusable logic patterns.

Methods

.add(condition: Predicate, branch: Function): DeferBranchDynamic
  • Adds a predicate-based conditional branch
  • condition is a function that returns boolean
  • First-match wins: the first truthy branch will be selected; later entries are ignored
.nomatch(handler: Function): DeferBranchDynamic
  • Sets a fallback handler for when no predicates match
  • Executes during .predicate() evaluation
.predicate(...args): void
  • Evaluates all conditions to find the first match
  • Call this before .run() to update the matched branch
  • Essential for dynamic behavior
.run(...args): any
  • Executes the currently matched branch
  • Returns the function's return value or undefined

deferedBranchAll()

Same as deferedBranch

deferedBranchAllDynamic()

Same as deferedBranchDynamic

Type Annotation

The factory functions deferedBranch, deferedBranchDynamic, deferedBranchAll, and deferedBranchAllDynamic are generic helpers. You can provide explicit type parameters to describe the branch function signature and the optional nomatch handler.

Below is an example using deferedBranch:

import { deferedBranch } from 'defered-branch';

// Here we declare that branches accept a message (string) and return void.
// The factory signature is: deferedBranch<BranchFn, NoMatchFn>()
const handler = deferedBranch<(msg: string) => void, () => void>();

handler
  .add(
    process.env.STATUS === 'ok',
    (msg) => console.log('OK:', msg) // this is restricted by `(msg: string) => void`
  )
  .add(
    process.env.STATUS === 'warn',
    (msg) => console.warn('WARN:', msg) // this is restricted by `(msg: string) => void`
  )
  .nomatch(
    () => console.debug('unknown') // this is restricted by `() => void`
  );

handler.run('hello world'); // input args for `run` are restricted by `(msg: string) => void`

Notes:

  • If you omit generic parameters TypeScript will fall back to AnyFn and inference is weaker.
  • BranchFn defines the parameter types that .run(...) accepts and what each branch receives.
  • NoMatchFn defines the signature of the nomatch/deferedNomatch handler.

Example: calculator with typed branches

const calc = deferedBranchDynamic<(a: number, b: number) => number, () => never>();

calc
  .add(
    () => operation === 'add',
    (a, b) => a + b
  )
  .add(
    () => operation === 'mul',
    (a, b) => a * b
  )
  .nomatch(() => {
    throw new Error('unknown operation');
  });

calc.predicate();
const result = calc.run(2, 3); // typed as number | undefined

License

MIT License - see LICENSE file for details.

Contributing

Contributions are welcome! Please feel free to submit issues and pull requests.

Trivia

KT.js is the reason of this package's birth. It uses deferedBranchDynamic internally to handle attribute and content processing in a clean, reusable way.


Made with ❤️ by Kasukabe Tsumugi (´。• ᵕ •。`) ♡