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

ts-fluent-builder

v1.2.10

Published

A TypeScript library for building types - 100% fluent, arbitrarily nested, zero/de minimis config with compile-time type & data safety mechanisms.

Readme

ts-fluent-builder

A powerful TypeScript library for building any complex type, 100% fluent within a single builder, arbitrarily nested, zero config, with full IntelliSense support and compile-time type & data safety mechanisms.

Features

  • Simple & Powerful: A single function to build any complex type, interface, array, tuple, record or object union
  • Type-Safe: Full TypeScript support with compile-time validation
  • Data-Safe: Prevents overwriting data or building incomplete objects
  • Fluent API: Intuitive method chaining for object construction
  • IntelliSense: Rich autocomplete and type hints in your IDE
  • Flexible: Works with any valid TypeScript type structure

Installation

npm install ts-fluent-builder
# or
yarn add ts-fluent-builder

Quick Start

import { fluentBuilder } from 'ts-fluent-builder';

// Define your types
interface User {
  id: number;
  name: string;
  email: string;
  addresses: Address[];
}

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

// Build objects fluently
const user = fluentBuilder<User>()
  .id(1)
  .name('John Doe')
  .email('[email protected]')
  .addressesArray()
    .pushObject()
      .street('123 Main St')
      .city('New York')
      .country('USA')
      .build()
    .push({
      street: '456 Oak Ave',
      city: 'Boston',
      country: 'USA'
    })
    .buildAddresses()
  .build();

API Reference

fluentBuilder<T>()

Creates a new fluent builder for the specified type.

Parameters:

  • T: The TypeScript type to build

Returns: A builder instance with functions ready to build the type

// objects
interface Person {
  name: string;
  age: number;
  address: Address;
}
const person = fluentBuilder<Person>()
  .name('Alice')
  .age(30)
  .addressObject()
    .street('123 Main St')
    .city('Springfield')
    .country('USA')
    .buildAddress()
  .build();
// arrays
const numbers = fluentBuilder<number[]>()
  .push(1)
  .push(2)
  .push(3)
  .build(); // [1, 2, 3]

interface TodoItem {
  id: number;
  title: string;
  completed: boolean;
}

interface TodoList {
  items: TodoItem[];
}

const todoList = fluentBuilder<TodoList>()
  .itemsArray()
    .pushObject()
      .id(1)
      .title('Buy groceries')
      .completed(false)
      .build()
    .pushObject()
      .id(2)
      .title('Walk the dog')
      .completed(true)
      .build()
    .buildItems()
  .build();
// tuples
const falsyValues = fluentBuilder<[boolean, number, bigint, string]>()
  .index0(false)
  .index1(0)
  .index2(0n)
  .index3('')
  .buildArray();
// polymorphic types via unions (currently only object unions are supported)
interface Shape {
  type: string;
  area: number;
}

interface Circle extends Shape {
  type: 'circle';
  radius: number;
}

interface Rectangle extends Shape {
  type: 'rectangle';
  width: number;
  height: number;
}

const shapes = fluentBuilder<(Circle | Rectangle)[]>()
  .pushObject()
    .type('circle')
    .area(Math.PI * 5 * 5)
    .radius(5)
    .buildElement()
  .pushObject()
    .type('rectangle')
    .area(20)
    .width(4)
    .height(5)
    .buildElement()
  .buildArray();
// records
interface Config {
  url: string;
  timeout: number;
  enabled: boolean;
}

const config = fluentBuilder<Record<string, Config>>()
  .set('production', {
    url: 'https://api.example.com',
    timeout: 5000,
    enabled: true
  })
  .setObject('development')
    .url('https://dev.api.example.com')
    .timeout(10000)
    .enabled(false)
    .buildDevelopment()
  .buildRecord();

Builder Methods

There are a few common patterns used:

Value Assignment

.propertyName(value)    // Set a property value on an object
.push(value)            // Append to an array
.set(key, value)        // Set a key value entry on a record
.indexN(value)          // Set indexed value on a tuple

Nested Builders

.propertyNameArray()    // Start building a nested array  
.propertyNameObject()   // Start building a nested object
.propertyNameRecord()   // Start building a nested record

.pushArray()            // Start building a nested array to push onto the array
.pushObject()           // Start building a nested object to push onto the array
.pushRecord()           // Start building a nested record to push onto the array

.indexNArray()          // Start building a nested array at the array index
.indexNObject()         // Start building a nested object at the array index
.indexNRecord()         // Start building a nested record at the array index

.setArray(name)         // Start building a nested array to set on the record
.setObject(name)        // Start building a nested sub-type to set on the record
.setRecord(name)        // Start building a nested record to set on the record

Termination

// Build and return either the result or the parent builder for continued chaining
.build()                

// all build...() functions are aliases of build() and can be used as hints to the developer, eg:
.buildPropertyName()
.buildRecordName()
.buildArray()
.buildObject()
.buildRecord()

Advanced Usage

Complex Nested Structures

interface Company {
  name: string;
  departments: Department[];
  settings: Record<string, any>;
}

interface Department {
  name: string;
  employees: Employee[];
  budget: number;
}

interface Employee {
  id: number;
  name: string;
  role: string;
}

const company = fluentBuilder<Company>()
  .name('TechCorp')
  .departmentsArray()
    .pushObject()
      .name('Engineering')
      .budget(500000)
      .employeesArray()
        .pushObject()
          .id(1)
          .name('John Doe')
          .role('Senior Developer')
          .build()
        .pushObject()
          .id(2)
          .name('Jane Smith')
          .role('Tech Lead')
          .build()
        .buildEmployees()
      .build()
    .buildDepartments()
  .settingsRecord()
    .set('theme', 'dark')
    .set('notifications', true)
    .set('autoSave', false)
    .buildSettings()
  .build();

Working with Optional Properties

The builder automatically handles optional properties and will only require you to set mandatory fields:

interface User {
  id: number;
  name: string;
  email?: string;  // optional
  phone?: string;  // optional
}

// This works - only required fields need to be set
const user = fluentBuilder<User>()
  .id(1)
  .name('John')
  .build();

// Optional fields can be added
const fullUser = fluentBuilder<User>()
  .id(1)
  .name('John')
  .email('[email protected]')
  .phone('+1234567890')
  .build();

Type Safety Features

Compile-Time Validation

ts-fluent-builder prevents common type and data mistakes at compile time:

interface User {
  id: number;
  name: string;
  email?: string;  // optional
  phone?: string;  // optional
}

// ❌ This won't compile - missing required property
const invalid = fluentBuilder<User>()
  .name('John')
  // .id(1) - missing required field
  .build();

// ❌ This won't compile - wrong type
const wrongType = fluentBuilder<User>()
  .id('not-a-number')  // id expects number
  .build();

// ❌ This won't compile - tuple not completely filled
const missingTupleElement = fluentBuilder<[boolean, string, number]>()
  .index0(true)
  .index1('abc')
  // .index2(123) - missing element
  .build();

// ❌ This won't compile - duplicate property
const duplicateProperty = fluentBuilder<User>()
  .id(1)
  .id(2)  // can't set id twice
  .build();

// ❌ This won't compile - duplicate record key
const duplicateKey = fluentBuilder<Record<string, boolean>>()
  .set('production', true)
  .set('production', false)  // can't set same key twice
  .build();

IntelliSense Support

  • Autocomplete for available properties
  • Type hints for expected values
  • Documentation in tooltips
  • Error highlighting for type mismatches

Best Practices

  1. Use TypeScript: ts-fluent-builder is designed for TypeScript and provides minimal value in plain JavaScript

  2. Define Interfaces or Types First: Always define your types before using the builders

  3. Leverage IntelliSense: Let your IDE guide you through the available methods

  4. Use the build...() Aliases: Help later developers easily see where they're looking in the build chain

Contributing

Contributions are very welcome! Please open an issue or submit a pull request on GitHub Issues.

License

This project is licensed under the MIT License - see the LICENSE file for details.


Happy Building!