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

@typescript-package/state

v2.0.0

Published

State management for TypeScript.

Readme

typescript-package/state

Simple state management for different types in TypeScript.

npm version GitHub issues GitHub license

Table of contents

Installation

npm install @typescript-package/state

Api

import {
  Ability,

  // Array.
  ArrayState,
  BooleanArrayState,
  NamedArrayState,
  NamedBooleanArrayState,

  // Boolean.
  Boolean,
  BooleanState,

  // Enum.
  Enum,
  EnumState,

  // Object.
  BooleanActionObjectState,
  BooleanObjectState,
  NamedObjectState,
  ObjectState,

  NullState,
  NumberState,
  ImmutableState,
  State
} from '@typescript-package/state';

Ability

import { Ability } from '@typescript-package/state';

// Extend the Ability class for a specific type
export class Connection extends Ability {}

// Initialize the connection.
const connection = new Connection();

// Disables the connection.
connection.disable();
connection.isDisabled();

// Enables the connection.
connection.enable();
connection.isEnabled();

ArrayState

import { ArrayState } from '@typescript-package/state';

// Extend the ArrayState class for a specific type
export class Numbers extends ArrayState<number> {
  // Additional custom methods specific to Numbers can be added if needed
}

// Initialize `Numbers`.
const numbers = new Numbers([27, 28, 29]);

// Append a number to the array state
numbers.append(30);
console.log(numbers.state); // Output: [27, 28, 29, 30]

// Insert a number at a specific index
numbers.insert(2, 99);
console.log(numbers.state); // Output: [27, 28, 99, 29, 30]

// Remove a number by index
numbers.remove(1);
console.log(numbers.state); // Output: [27, 99, 29, 30]

// Pick specific indexes
const picked = numbers.pick(0, 2);
console.log(picked); // Output: [27, 29]

// Swap two elements
numbers.swap(1, 3);
console.log(numbers.state); // Output: [27, 30, 29, 99]

// Reset the state to its initial state
numbers.reset();
console.log(numbers.state); // Output: [27, 28, 29]

A simple queue implementation.

import { ArrayState } from '@typescript-package/state';

// Extend the ArrayState class for a specific type
export class Queue extends ArrayState<number> {
  /**
   * Adds an item to the end of the queue (enqueue operation).
   * @param {number} value - The number to add to the queue.
   * @returns {this}
   */
  public enqueue(value: number): this {
    return this.append(value);
  }

  /**
   * Removes and returns the item at the front of the queue (dequeue operation).
   * @returns {number | undefined} - The dequeued number or undefined if the queue is empty.
   */
  public dequeue(): number | undefined {
    const front = this.first();
    this.remove(0); // Remove the first element
    return front;
  }

  /**
   * Returns the item at the front of the queue without removing it.
   * @returns {number | undefined} - The number at the front of the queue.
   */
  public peek(): number | undefined {
    return this.first();
  }

  /**
   * Checks if the queue is empty.
   * @returns {boolean} - True if the queue is empty, false otherwise.
   */
  public isEmpty(): boolean {
    return this.length === 0;
  }
}

// Initialize `Queue`.
const queue = new Queue([27, 28, 29]);

// Enqueue a number
queue.enqueue(30);
console.log(queue.state); // Output: [27, 28, 29, 30]

// Dequeue a number
const dequeued = queue.dequeue();
console.log(dequeued); // Output: 27
console.log(queue.state); // Output: [28, 29, 30]

// Peek at the front of the queue
const front = queue.peek();
console.log(front); // Output: 28

// Check if the queue is empty
console.log(queue.isEmpty()); // Output: false

// Dequeue all items
queue.dequeue();
queue.dequeue();
queue.dequeue();
console.log(queue.isEmpty()); // Output: true

BooleanArrayState

import { BooleanArrayState as AbstractBooleanArrayState } from '@typescript-package/state';

// Extend the AbstractBooleanArrayState class for a specific type
export class BooleanArrayState extends AbstractBooleanArrayState {
  // Additional custom methods specific to BooleanArrayState can be added if needed
}

let booleanArrayState = new BooleanArrayState(false, false, true, true);

// Sets all values to `false`.
booleanArrayState.false();
console.log(booleanArrayState.state); // Output: [false, false, false, false]

// Toggles all values to `true`.
booleanArrayState.toggle();
console.log(booleanArrayState.state); // Output: [true, true, true, true]

// Toggles all values to `false`.
booleanArrayState.toggle();
console.log(booleanArrayState.state); // Output: [false, false, false, false]

// Sets all values to `true`.
booleanArrayState.true();
console.log(booleanArrayState.state); // Output: [true, true, true, true]

NamedArrayState

import { NamedArrayState } from '@typescript-package/state';

// Extend the NamedArrayState class for a specific type
export class AppConfiguration extends NamedArrayState<'theme' | 'language' | 'notifications', string | boolean> {
  constructor() {
    super(
      ['theme', 'language', 'notifications'], // Names of the configuration settings
      ['dark', 'en', true]                    // Default values
    );
  }

  /**
   * Updates the value of a specific configuration by name.
   * @param {string} name - The name of the configuration to update.
   * @param {string | boolean} value - The new value to set.
   */
  public updateConfiguration(name: 'theme' | 'language' | 'notifications', value: string | boolean) {
    this.update(this.indexOf(name), value);
  }
}

// Initialize.
const config = new AppConfiguration();

// View the current state as an object
console.log(config.toObject()); // Output: { theme: 'dark', language: 'en', notifications: true }

// Get the value of a specific setting
console.log(config.get('theme')); // Output: 'dark'

// Update a specific configuration setting
config.updateConfiguration('theme', 'light');
console.log(config.get('theme')); // Output: 'light'

// Selecting multiple configuration options
const selectedValues = config.select('theme', 'language');
console.log(selectedValues); // Output: ['light', 'en']

// Retrieve state with names as tuples
console.log(config.stateWithNames); // Output: [['theme', 'light'], ['language', 'en'], ['notifications', true]]

// Reset the configuration state to its initial value
config.reset();
console.log(config.toObject()); // Output: { theme: 'dark', language: 'en', notifications: true }

BooleanState

import { BooleanState } from '@typescript-package/state';

export class ActiveState extends BooleanState {
  public override get state() {
    return super.state;
  }

  public override false() {
    super.false();
    return this;
  }

  public activate() {
    super.true();
  }

  public deactivate() {
    super.false();
  }
}

// Initialize.
const activeState = new ActiveState();

// Deactivate the initial state.
activeState.deactivate();

EnumState

import { EnumState } from '@typescript-package/state';

// Define example enum.
enum Active {
  Yes,
  No
}

// Use the `EnumState`.
export class ActiveEnum extends EnumState<typeof Active, Active> {
  constructor(state: Active) {
    super(state, Active);
  }
}

// Initialize.
const activeEnum = new ActiveEnum(Active.No);

// Check whether enum is set to `No`.
activeEnum.is(Active.No)

BooleanActionObjectState

import { BooleanActionObjectState } from '@typescript-package/state';

// Extend the BooleanActionObjectState class for a specific type
export class Connection<Names extends PropertyKey, Actions extends string> extends BooleanActionObjectState<Names, Actions> {
  /**
   * Checks whether connection is connected.
   * @returns {boolean}
   */
  public isConnected() {
    return this.is("connected" as any, true);
  }
}
// Initialize the `Connection` with state `connected` and actions `connect` and `disconnect`.
const connection = new Connection(['connected'], ['connect', 'disconnect']);

// Dispatches the `connect` action.
connection.dispatch('connect');
console.log(connection.isConnected()); // Output: true

// Dispatches the `disconnect` action.
connection.dispatch('disconnect');
console.log(connection.isConnected()); // Output: false

// Dispatches the `connect` action.
connection.dispatch('connect');
console.log(connection.isConnected()); // Output: true

NullState

import { NullState } from '@typescript-package/state';

// Use the `NullState`.
export class Nullified extends NullState {}

// Initialize.
const nullified = new Nullified();

// Sets the state to `null`.
nullified.set();

// Sets the state to `undefined`.
nullified.unset();

NumberState

import { NumberState } from '@typescript-package/state';

// Use the `NumberState`.
export class NumberedState extends NumberState {
  public override reset() {
    super.reset();
    return this;
  }
}

// Initialize.
const numberedState = new NumberedState();

// Decrement state by 1.
numberedState.decrement();

// Increment state by 1.
numberedState.increment();

// Increment state by 5.
numberedState.increment(5);

// Reset state to 0.
numberedState.reset();

Immutability

Sealed

Provides structural immutability, but not value immutability. The least strict form of immutability.

Frozen

Provides structural and shallow immutability. Stricter than seal.

Locked

It's not native JavaScript state. Combines the features of freeze but extends immutability to nested structures(deep immutability).

GIT

Commit

Versioning

Semantic Versioning 2.0.0

Given a version number MAJOR.MINOR.PATCH, increment the:

  • MAJOR version when you make incompatible API changes,
  • MINOR version when you add functionality in a backwards-compatible manner, and
  • PATCH version when you make backwards-compatible bug fixes.

Additional labels for pre-release and build metadata are available as extensions to the MAJOR.MINOR.PATCH format.

FAQ How should I deal with revisions in the 0.y.z initial development phase?

The simplest thing to do is start your initial development release at 0.1.0 and then increment the minor version for each subsequent release.

How do I know when to release 1.0.0?

If your software is being used in production, it should probably already be 1.0.0. If you have a stable API on which users have come to depend, you should be 1.0.0. If you’re worrying a lot about backwards compatibility, you should probably already be 1.0.0.

License

MIT © typescript-package (license)