@aurbi/tiny-composite-builder
Version:
Small framework for taking base objects and adding extensions using a builder pattern, but with full and strict compile-time type support.
48 lines (47 loc) • 2.87 kB
TypeScript
import { IBaseHint, IBase } from "./IBase";
import { IExtension } from "./IExtension";
import { ExtConsOfBuilder, Constructor, BuilderWithExt, ConstructedType, DropFirst, ExtensionConstructionArray, ConstructedExtensions } from "./Utility";
/**
* A function that provides a consumer the ability to extend the base with extensions.
* @typeparam T extends ExtensibleBase: what kind of extensible object are we creating?
* @typeparam A: original form of the builder
* @typeparam B: new form of the builder
*/
export type BuilderFunction<T extends IBaseHint, A extends Builder<T>, B extends Builder<T>> = (b: A) => B;
export type ConstructorParams<T extends new (...args: any) => any> = T extends new (...args: infer P) => any ? P : never;
/**
* A builder that should produce a base
* @typeparam T extends ExtensibleBase: what kind of extensible object are we creating?
*/
export declare class Builder<TBase extends IBaseHint, TExts extends ExtensionConstructionArray<TBase> = []> {
private _base;
/**
* Create a new ExtensibleBase object with optional extensions, added via a builder function.
* @param builder Builder function that describes the desired extensions for the object
* @returns New instance of ExtensibleBase object with the requested extensions present
*/
static Create<TBase extends IBaseHint<TBase>, TBuilder extends Builder<TBase, any>>(base: Constructor<TBase>, builder: BuilderFunction<TBase, Builder<TBase>, TBuilder>, ...args: any): IBase<TBase, ConstructedExtensions<TBase, ExtConsOfBuilder<TBuilder>>>;
private constructor();
private _extensions;
private _methodNameFilter;
/**
* Add a compatible extension to be grafted onto the base.
* @param extClass Extension class (non-instantiated: use the class name as a value!)
* @param args Arguments, if any, to pass along to the extension constructor. Do not include the
* Base instance parameter, this is automatically provided to the extension constructor later.
* @returns The builder, now aware of this extension
*/
with<TSelf extends Builder<TBase, TExts>, TNewExt extends Constructor<IExtension<TBase>>>(this: TSelf, extClass: TNewExt, ...args: DropFirst<ConstructorParams<TNewExt>>): BuilderWithExt<TBase, TSelf, ConstructedType<TNewExt>>;
/**
* Change the default method name filter for creating extension forwarding functions in the base.
*
* By default, this is `(m) => m.startsWith('$')`, meaning only public functions that start with
* a dollar sign ($) have method forwarders constructed on the base instance.
*
* You can disable method forwarding entirely by just setting this to `() => false`.
* @param f method name filter
* @returns The builder, with modified filter.
*/
withMethodNameFilter(f: (m: string) => boolean): this;
private make;
}