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 🙏

© 2025 – Pkg Stats / Ryan Hefner

monomorph

v1.3.0

Published

Monomorph

Downloads

315

Readme

Monomorph is a Typescript and Javascript library for performance-critical applications. Monomorph was originally developed by Hamza Kubba to power Bounce, a free & open source physics library for the web. Monomorph also powers MECS, a free & open source ECS library.

With Monomorph, you can easily create classes that:

  • have built-in object pooling to minimize garbage collection
  • can nest and/or reference monomorph classes
  • have built-in performant serialization/deserialization methods for data (including handling nesting and references), as well as other utility methods like .copy() which copies including nested object values.
  • keep more methods monomorphic, avoiding potential slowdowns of up to 60x
  • avoid repetitive boilerplate
  • are strongly typed, when using Typescript

How it works

In a nutshell, Monomorph dynamically creates the JS code for a class based on the schema you provide, and you extend that class. Each generated class has unique helper methods that are not inherited, which avoids performance drops that result from class inheritance in JS. Read "Keep in Monomorphic" for more info about monomorphism, why it matters, and how this library helps.

Install into your project

npm install monomorph

Usage

Basic class schema (Typescript)

Let's say we want to create a Vector2 class, which has x and y numbers on it. This is what that would look like in

import { createClass, NumberType, PropertyDefinitionMap } from 'monomorph';

const props = {
  // x and y are numbers with default value 0
  x: NumberType(0),
  y: 0,
  // ^^ this is shorthand for:
  // y: NumberType(0)
} as const satisfies PropertyDefinitionMap;

class Vector2 extends createClass<Vector2, typeof props>(props) {
  /* your methods here, for example add() */
  add(otherVec2: Vector2) {
    this.x += otherVec2.x;
    this.y += otherVec2.y;
  }
}
import { createClass, NumberType } from 'monomorph';

const props = {
  // x and y are numbers with default value 0
  x: NumberType(0),
  y: 0,
  // ^^ this is shorthand for:
  // y: NumberType(0)
};

class Vector2 extends createClass(props) {
  /* your methods here, for example add() */
  add(otherVec2) {
    this.x += otherVec2.x;
    this.y += otherVec2.y;
  }
}

Using Monomorph classes

// Vector2 defined above

const v1 = Vector2.create(); // x and y are 0
const v2 = Vector2.create({ x: 1, y: 2 });
const v3 = Vector2.create({ x: 3 }); // y is 0

v1.copy(v2); // built-in method, now v1 has the same values as v2

v1.add(v3); // custom method defined above

console.log(v1.x); // 4  (1 + 3)
console.log(v1.y); // 2  (2 + 0)

Object pooling

Monomorph automatically creates a Pool class the class you create with it. For example, with the Vector2 class defined above, Vector2.Pool is the pool class. This is how you use it.

// Vector2 defined above

const vector2Pool = new Vector2.Pool();

// v1 is created inside vector2Pool
const v1 = Vector2.create({ x: 1, y: 2 }, vector2Pool);

// v2 is created in the same pool as v1 (also in vector2Pool)
const v2 = v1.createInPool({ x: 3, y: 4 });

// alternate syntax
const v3 = Vector2.create({ x: 5, y: 6 }, v1.pool);

for (const vector2 of vector2Pool) {
  // loops over v1, v2, v3
}

// v2 is returned to the pool, and references to it that use ReferenceType(Vector2) will resolve as null
v2.destroy();

for (const vector2 of vector2Pool) {
  // because we used v2.destroy(), this now loops over v1, v3
}

// creating v4 now will automatically reuses the v2 object
const v4 = Vector2.create({ x: 7, y: 8 }, vector2Pool);

for (const vector2 of vector2Pool) {
  // loops over v1, v4, v3
}
import { createClass, ChildType } from 'monomorph';

// Vector2 as defined above in the "Basic class schema" section

const boundsProps = {
  min: ChildType(Vector2),

  max: Vector2,
  // ^^ this is shorthand for:
  // max: ChildType(Vector2),
};

class Bounds extends createClass(boundsProps) {}

const bounds = Bounds.create({
  min: { x: -1, y: -2 },
  max: { x: 10, y: 5 },
});


const array = new Float64Array(); // can also be Float32Array or a basic js Array
aabb.toArray(array); // automagically generated method

const aabb2 = Aabb.create(); // create with default values
aabb2.fromArray(array); // now aabb2 has the same values as aabb

const aabb3 = Aabb.createFromArray(array); // same as aabb2 in one step

Additional and advanced examples

There are many more examples written in Typescript in the tests folder, including BooleanType, ReferenceType, ReferenceListType and others, as well as handling the serialization and deserialization of pools that have references, and multiple pools to/from a single array.

Roadmap

  • Add a generic non-monomorph type for holding references
  • More official benchmarks; basic benchmarks were added in version 1.0.1 but more extensive benchmarks would be good
  • Fixing bugs: while Monomorph is heavily used in our physics library Bounce, there may be bugs around edge cases and untested complex combinations. Please file an issue if you run into problems
  • More supported types: Strings are partially implemented and not considered fully supported yet, other types will be added based on requests and code contributions
  • Want to see something here? Please create an issue on codeberg

How to contribute

If you like this project and would like to support our work, please consider contributing code via pull requests, or donating via open collective. Contributions are greatly appreciated!