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

auto-ts-builder

v0.0.5

Published

Runtime TypeScript builder utility for interfaces and types with fluent chaining

Readme

auto-ts-builder

GitHub license npm version npm bundle size downloads

auto-ts-builder is a powerful TypeScript utility library for creating fully type-safe builders that follow the builder pattern. It provides an elegant API for constructing complex objects with clear, chainable methods and deep property navigation.


Features

  • Type-safe Builder Pattern: Create builders with full TypeScript type checking and autocompletion.
  • Intuitive Method Chaining: Fluent interface with seamless method chaining for a clean API.
  • Deep Object Navigation: Navigate through nested objects with property access syntax.
  • Smart Naming Conventions: Automatically adapts to various naming styles (camelCase, PascalCase, etc.).
  • Custom Helper Methods: Extend builders with custom helper methods for enhanced functionality.
  • Zero Dependencies: Minimal footprint with only lodash as a dependency.

Installation

Install the library via npm or yarn:

# Using npm
npm install auto-ts-builder

# Using yarn
yarn add auto-ts-builder

Usage

Basic Example

import { aBuilder } from 'auto-ts-builder';

interface Person {
  name: string;
  age: number;
  address: {
    street: string;
    city: string;
    zip: string;
  };
}

// Create a builder with default values
const personBuilder = aBuilder<Person>()({ 
  name: 'John', 
  age: 30, 
  address: {
    street: '123 Main St',
    city: 'Anytown',
    zip: '12345'
  }
});

// Use the builder to create a modified object
const person = personBuilder
  .withName('Jane')
  .withAge(25)
  .address.withStreet('456 Elm St')
  .build();

console.log(person);
/* Output:
{
  name: 'Jane',
  age: 25,
  address: {
    street: '456 Elm St',
    city: 'Anytown',
    zip: '12345'
  }
}
*/

Using Custom Helper Methods

import { aBuilderHelper } from 'auto-ts-builder';

interface Person {
  name: string;
  age: number;
  address: {
    street: string;
    city: string;
    zip: string;
  };
}

// Create a builder with default values and custom helpers
const personBuilder = aBuilderHelper<Person>()(
  {
    name: 'John',
    age: 30,
    address: {
      street: '123 Main St',
      city: 'Anytown',
      zip: '12345'
    }
  },
  (builder) => ({
    withFullName: (firstName: string, lastName: string) => 
      builder.withName(`${firstName} ${lastName}`),
    withAgeIncrement: (increment: number = 1) => 
      builder.withAge(builder.build().age + increment),
    address: {
      withFullAddress: (street: string, city: string, zip: string) => {
        builder.address.withStreet(street);
        builder.address.withCity(city);
        builder.address.withZip(zip);
      }
    }
  })
);

// Use the builder with custom helpers
const person = personBuilder
  .withFullName('Jane', 'Doe')
  .withAgeIncrement(2)
  .address.withFullAddress('789 Oak St', 'New City', '67890')
  .build();

console.log(person);
/* Output:
{
  name: 'Jane Doe',
  age: 32,
  address: {
    street: '789 Oak St',
    city: 'New City',
    zip: '67890'
  }
}
*/

Working with Nested Builders

import { aBuilder } from 'auto-ts-builder';

interface Address {
  street: string;
  city: string;
  zip: string;
}

interface Person {
  name: string;
  age: number;
  address: Address;
}

// Create separate builders
const addressBuilder = aBuilder<Address>()({
  street: '123 Main St',
  city: 'Anytown',
  zip: '12345'
});

const personBuilder = aBuilder<Person>()({
  name: 'John',
  age: 30,
  address: addressBuilder.build()
});

// Modify both builders
addressBuilder.withStreet('456 Elm St').withCity('New City');
personBuilder.withName('Jane').withAge(25).withAddress(addressBuilder.build());

console.log(personBuilder.build());
/* Output:
{
  name: 'Jane',
  age: 25,
  address: {
    street: '456 Elm St',
    city: 'New City',
    zip: '12345'
  }
}
*/

API

aBuilder<T>()

Creates a builder factory for objects of type T - can be extended with helpers. helpers with same name will override the default builder methods.

Generic Types

  • T: The type of object to build, typically an interface or type.

Returns

A function that takes the default object and returns a builder with methods for each property:

  • For each property prop in T, generates a withProp method.
  • For nested objects, provides property access to nested builders.
  • Includes a build() method to create the final object.

aBuilderHelper<T>()

Creates a builder factory which exports only the helper methods. the internal implementation will only be accessible inside the helpers function.

Generic Types

  • T: The type of object to build.

Returns

A function that takes:

  1. The default object of type T.
  2. An optional function that receives a builder and returns an object with custom helpers.

Helpers Function Behavior

helpers?: (builder: Builder) => ({...});
  • Important: All helper functions ignore their own return values and always return the root builder for chaining
  • The builder parameter provided to the helper function:
    • Contains only internal builder methods (not other helper methods)

Example Helper Function Usage

// Example of proxying an existing method with enhanced functionality
withName: (firstName, lastName) => builder.withName(`${firstName} ${lastName}`),

// Example of a helper that uses multiple internal methods
withAddress: (street, city, zip) => {
  builder.address.withStreet(street);
  builder.address.withCity(city);
  builder.address.withZip(zip);
  // No need to return anything - always returns the root builder
},

// Example of nested helpers
address: {
  withPrimary: (address) => builder.address.withType('primary').withValue(address)
}

The result is a builder with all standard methods plus the custom helpers.


Type-Safe Builder Pattern

The library automatically generates appropriate builder methods based on property names:

  • Regular properties: withName for a name property
  • PascalCase properties: with_Name for a Name property
  • Underscore properties: with_UnderScore for _UnderScore properties

All methods maintain proper typing for complete type safety.


Why Use auto-ts-builder?

  • Type Safety: Full TypeScript support ensures your builders are type-safe.
  • Clean API: The builder pattern provides a clean, fluent interface for object construction.
  • Flexibility: Easily extend with custom helpers for domain-specific building logic.
  • Immutability: Each builder operation creates a new state, maintaining immutability.
  • Readability: Makes code more readable and maintainable with clear intentions.

License

MIT © Guy Warzager


Limitations

Discriminated Unions

Discriminated unions have partial support in auto-ts-builder:

  • ✅ Supported: Using discriminated unions as fields or nested properties

    // This works fine
    const aMyTypeBuilder = aBuilder<{ discriminated: MyType }>()({...})
  • ❌ Not supported: Using a discriminated union as the root type

    // This won't work properly
    const aMyTypeBuilder = aBuilder<
      { type: 'row'; row: { row: number; error: string } } |
      { type: 'global'; global: { error: string } }
    >()({...})
  • Not supported: Partial nested property access for discriminated unions

    ❌ // This won't work
    aMyTypeBuilder.discriminated.withType('row').withRow({
        row: 2,
        error: 'error',
    })
    
    ✅ // This will work
    aMyTypeBuilder.withDiscriminated({
                  type: 'row',
                  row: {
                      row: 2,
                      error: 'error',
                  },
              });

Workaround: Use separate builders for each type in your discriminated union.


Contribution

Contributions, issues, and feature requests are welcome!