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

typeomatica

v0.3.57

Published

type logic against javascript metaprogramming

Readme

TypeØmatica

Coverage Status

NPM GitHub package.json version GitHub last commit

$ npm install typeomatica

This package is a part of mnemonica project.

Strict Runtime Type Checker for JavaScript Objects

TypeØmatica uses JavaScript Proxies to enforce type safety at runtime, exactly as TypeScript expects at compile time. Once a property is assigned a value, its type is locked and cannot be changed.


Quick Start

import { BaseClass } from 'typeomatica';

class User extends BaseClass {
  name: string = 'default';
  age: number = 0;
}

const user = new User();

// ✓ Valid assignments
user.name = 'John';
user.age = 25;

// ✗ Runtime error (even if TypeScript is bypassed with @ts-ignore)
user.age = '25';  // TypeError: Type Mismatch

Table of Contents


What is TypeØmatica?

TypeØmatica provides strict runtime type checking for JavaScript objects using Proxy-based interception. It ensures that once a property is initialized with a type, that type cannot be violated at runtime.

Key Features:

  • Runtime type enforcement (complements TypeScript's compile-time checks)
  • Proxy-based property interception
  • Type locking after initial assignment
  • Prevents prototype mutation, property redefinition, and deletion

Installation

npm install typeomatica

Core Concepts

How It Works

TypeØmatica wraps objects with JavaScript Proxies that intercept:

  • get - Property reads
  • set - Property writes (with type validation)
  • setPrototypeOf - Blocks prototype changes
  • defineProperty - Blocks property redefinition
  • deleteProperty - Blocks property deletion

Type Categories

| Category | Types | Behavior | |----------|-------|----------| | primitives | string, number, boolean, bigint, symbol, undefined | Type-locked accessors | | nullish | null | Only null allowed | | objects | object, arrays, dates | Same constructor type required | | functions | methods | Restricted on data types |


API Reference

BaseClass

The primary class for strict-type objects.

import { BaseClass } from 'typeomatica';

class MyClass extends BaseClass {
  field: string = 'value';
  constructor() {
    super();
  }
}

BasePrototype

Functional equivalent of BaseClass.

import { BasePrototype } from 'typeomatica';

const Base = BasePrototype({ initialProp: 123 });
class MyClass extends Base { }

@Strict() Decorator

Apply strict typing without extending BaseClass.

import { Strict } from 'typeomatica';

@Strict({ deep: true })
class MyClass {
  field: number = 0;
}

Decorator Arguments:

  • First argument: Base prototype or options object
  • Second argument: Options object

Options Interface

interface TypeomaticaOptions {
  strictAccessCheck?: boolean;  // default: false
}

Options:

  • strictAccessCheck: true - Enables strict receiver checking (throws ACCESS_DENIED error when property is accessed from wrong context)
  • deep: true - Enable recursive property checking (when using BasePrototype with initial values)

Usage with Options

// With BaseClass - strict access checking enabled
class SecureData extends BaseClass {
  secret: string = '';
  constructor() {
    super(undefined, { strictAccessCheck: true });
  }
}

// With BasePrototype - strict access checking enabled
const SecureBase = BasePrototype({ data: '' }, { strictAccessCheck: true });
class User extends SecureBase {
  name: string = '';
}

// With @Strict decorator - strict access checking enabled
@Strict(undefined, { strictAccessCheck: true })
class Product {
  price: number = 0;
}

Symbol Exports

import { 
  SymbolTypeomaticaProxyReference,  // Access proxy internals
  SymbolInitialValue                 // Access original values
} from 'typeomatica';

Usage Patterns

Pattern 1: Extending BaseClass

import { BaseClass } from 'typeomatica';

class User extends BaseClass {
  name: string = '';
  age: number = 0;
  active: boolean = true;
}

const user = new User();
user.name = 'John';     // ✓ Works
user.age = 25;          // ✓ Works

// @ts-ignore
user.age = '25';        // ✗ TypeError: Type Mismatch

Pattern 2: @Strict Decorator

import { Strict } from 'typeomatica';

@Strict({ deep: true })
class Product {
  id: number = 0;
  title: string = '';
  price: number = 0;
}

const product = new Product();
product.price = 29.99;      // ✓ Works
// @ts-ignore
product.price = '$29.99';   // ✗ TypeError: Type Mismatch

Pattern 3: BaseClass as Prototype

import { BaseClass } from 'typeomatica';

class UserData {
  name: string = 'default';
  age: number = 0;
}

// Inject type checking into prototype chain
Object.setPrototypeOf(UserData.prototype, new BaseClass({ deep: true }));

const user = new UserData();
user.name = 'John';     // ✓ Works
// @ts-ignore
user.name = 123;        // ✗ TypeError: Type Mismatch

Type Examples

Primitives

import { BaseClass } from 'typeomatica';

class Primitives extends BaseClass {
  str: string = 'hello';
  num: number = 42;
  bool: boolean = true;
  bigint: bigint = BigInt(100);
}

const p = new Primitives();
p.str = 'world';          // ✓ Works
p.num = 100;              // ✓ Works
// @ts-ignore
p.str = 123;              // ✗ TypeError: Type Mismatch

Null and Undefined

class Nullable extends BaseClass {
  nullValue: null = null;
  undefinedValue: undefined = undefined;
}

const n = new Nullable();
n.nullValue = null;              // ✓ Works
// @ts-ignore
n.nullValue = undefined;         // ✗ TypeError: Type Mismatch

Objects

class WithObject extends BaseClass {
  data: object = {};
  list: number[] = [];
}

const w = new WithObject();
w.data = { a: 1 };              // ✓ Works
w.list = [1, 2, 3];             // ✓ Works
// @ts-ignore
w.data = 123;                   // ✗ TypeError: Type Mismatch
// @ts-ignore
w.data = new Set();             // ✗ TypeError: Type Mismatch (Set !== Object)

Working with Wrapped Values

TypeØmatica wraps primitives to enforce type safety. Use valueOf() for operations.

Numeric Operations

class Calc extends BaseClass {
  count: number = 10;
}

const calc = new Calc();

// ✗ Direct arithmetic throws
const result = calc.count + 5;  // ReferenceError: Value Access Denied

// ✓ Use valueOf()
const result = calc.count.valueOf() + 5;  // 15
const sum = 3 + +calc.count;               // 13

String Operations

class Text extends BaseClass {
  message: string = 'hello';
}

const text = new Text();
text.message.valueOf().toUpperCase();  // 'HELLO'
text.message.valueOf().length;         // 5

Error Reference

| Error Message | Error Type | When Thrown | |---------------|------------|-------------| | Type Mismatch | TypeError | Wrong type assigned to property | | Value Access Denied | ReferenceError | Property accessed from wrong context (only when strictAccessCheck: true) | | Attempt to Access to Undefined Prop | Error | Reading non-existent property | | Functions are Restricted | TypeError | Function assigned to data property | | Re-Assirnment is Forbidden | TypeError | Modifying read-only custom field | | Setting prototype is not allowed | Error | Calling Object.setPrototypeOf() | | Defining new Properties is not allowed | Error | Calling Object.defineProperty() | | Properties Deletion is not allowed | Error | Calling delete on property |


Integration with Mnemonica

TypeØmatica integrates seamlessly with mnemonica for combined prototype inheritance and runtime type safety.

import { decorate } from 'mnemonica';
import { BaseClass, Strict } from 'typeomatica';

@decorate()
@Strict()
class Entity extends BaseClass {
  id: string = '';
  createdAt: Date = new Date();
}

// Works with mnemonica's inheritance system
const User = Entity.define('User', function(this: { email: string }) {
  this.email = '';
});

const user = new User();
// @ts-ignore
user.email = 123;  // ✗ TypeError: Type Mismatch

Decorator Order Matters:

  • @Strict() must come AFTER @decorate() (inner decorator)
  • Decorators apply bottom-to-top

For complete integration documentation, see mnemonica's TypeØmatica guide.


License

MIT

Copyright (c) 2019-2024 https://github.com/wentout