Skip to content

Matchbox Factories

The matchboxFactory function creates factories for working with tagged unions in TypeScript, providing type-safe pattern matching, exhaustiveness checking, and comprehensive type inference.

Its main features include:

  1. Factory Functions - Create tagged union instances with proper typing
  2. Pattern Matching - Match against union variants with exhaustiveness checking
  3. Type Predicates - Built-in type guards with the is method
  4. Type Assertion - Convert between variants with the as method
  5. Complete Type Inference - Full inference with minimal type annotations

You can create a factory using the matchboxFactory function. This factory then provides functions to create individual tagged union instances:

import { function matchboxFactory<Config extends TaggedTypes | string, TagProp extends string = "tag", R = MatchboxFactory<Config extends readonly string[] ? { [K in Config[number]]: (data: any) => any; } : Config, TagProp>>(config: Config, tagProp?: TagProp): R
Create a tagged union from a record mapping tags to value types, along with associated variant constructors, type predicates and `match` function.
@templateConfig - The configuration object or array of tags@templateTagProp - The property name used for the tag (default: "tag")@returnsAn object with constructors for each variant, type predicates, and match function@example```ts // Define a union of variants for a Result type const Result = matchboxFactory({ Ok: (value: number) => ({ value }), Err: (error: string) => ({ error }), }); // Create instances const ok = Result.Ok(42); const err = Result.Err("fail"); // Type predicates ok.is("Ok"); // true err.is("Err"); // true // Pattern matching const message = ok.match({ Ok: ({ value }) => `Value: ${value}`, Err: ({ error }) => `Error: ${error}`, }); // message === "Value: 42" ```
matchboxFactory
} from "matchina";
export const
const Light: MatchboxFactory<{
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
Light
=
matchboxFactory<{
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag", MatchboxFactory<{
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">>(config: {
    ...;
}, tagProp?: "tag" | undefined): MatchboxFactory<...>
Create a tagged union from a record mapping tags to value types, along with associated variant constructors, type predicates and `match` function.
@templateConfig - The configuration object or array of tags@templateTagProp - The property name used for the tag (default: "tag")@returnsAn object with constructors for each variant, type predicates, and match function@example```ts // Define a union of variants for a Result type const Result = matchboxFactory({ Ok: (value: number) => ({ value }), Err: (error: string) => ({ error }), }); // Create instances const ok = Result.Ok(42); const err = Result.Err("fail"); // Type predicates ok.is("Ok"); // true err.is("Err"); // true // Pattern matching const message = ok.match({ Ok: ({ value }) => `Value: ${value}`, Err: ({ error }) => `Error: ${error}`, }); // message === "Value: 42" ```
matchboxFactory
({
// Off state with no parameters type Off: undefinedOff: var undefinedundefined, // On state with optional brightness percentage
type On: (percentage?: number) => {
    percentage: number;
}
On
: (percentage: numberpercentage = 100) => ({ percentage: numberpercentage }),
}); // Create light instances const
const off: MatchboxMember<"Off", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
off
=
const Light: MatchboxFactory<{
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
Light
.
type Off: () => MatchboxMember<"Off", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
Off
();
const
const onFull: MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
onFull
=
const Light: MatchboxFactory<{
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
Light
.
type On: (percentage?: number | undefined) => MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
On
(); // Uses default 100%
const
const dimmed: MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
dimmed
=
const Light: MatchboxFactory<{
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
Light
.
type On: (percentage?: number | undefined) => MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
On
(50); // 50% brightness
const { const percentage: numberpercentage } =
const dimmed: MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
dimmed
.
data: {
    percentage: number;
}
data
;
export {
const off: MatchboxMember<"Off", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
export off
off
,
const onFull: MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
export onFull
onFull
,
const dimmed: MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
export dimmed
dimmed
,
const percentage: number
export percentage
percentage
};

By default, the tag property is named tag, but you can customize it:

const 
const states: MatchboxFactory<{
    Idle: () => {};
    Done: (x: number) => {
        result: number;
    };
}, "key">
states
=
matchboxFactory<{
    Idle: () => {};
    Done: (x: number) => {
        result: number;
    };
}, "key", MatchboxFactory<{
    Idle: () => {};
    Done: (x: number) => {
        result: number;
    };
}, "key">>(config: {
    Idle: () => {};
    Done: (x: number) => {
        result: number;
    };
}, tagProp?: "key" | undefined): MatchboxFactory<...>
Create a tagged union from a record mapping tags to value types, along with associated variant constructors, type predicates and `match` function.
@templateConfig - The configuration object or array of tags@templateTagProp - The property name used for the tag (default: "tag")@returnsAn object with constructors for each variant, type predicates, and match function@example```ts // Define a union of variants for a Result type const Result = matchboxFactory({ Ok: (value: number) => ({ value }), Err: (error: string) => ({ error }), }); // Create instances const ok = Result.Ok(42); const err = Result.Err("fail"); // Type predicates ok.is("Ok"); // true err.is("Err"); // true // Pattern matching const message = ok.match({ Ok: ({ value }) => `Value: ${value}`, Err: ({ error }) => `Error: ${error}`, }); // message === "Value: 42" ```
matchboxFactory
(
{ type Idle: () => {}Idle: () => ({}),
type Done: (x: number) => {
    result: number;
}
Done
: (x: numberx: number) => ({ result: numberresult: x: numberx }),
}, "key" ); const
const events: MatchboxFactory<{
    add: (x: number, y: number) => {
        x: number;
        y: number;
    };
    square: (x: number) => number;
}, "type">
events
=
matchboxFactory<{
    add: (x: number, y: number) => {
        x: number;
        y: number;
    };
    square: (x: number) => number;
}, "type", MatchboxFactory<{
    add: (x: number, y: number) => {
        x: number;
        y: number;
    };
    square: (x: number) => number;
}, "type">>(config: {
    ...;
}, tagProp?: "type" | undefined): MatchboxFactory<...>
Create a tagged union from a record mapping tags to value types, along with associated variant constructors, type predicates and `match` function.
@templateConfig - The configuration object or array of tags@templateTagProp - The property name used for the tag (default: "tag")@returnsAn object with constructors for each variant, type predicates, and match function@example```ts // Define a union of variants for a Result type const Result = matchboxFactory({ Ok: (value: number) => ({ value }), Err: (error: string) => ({ error }), }); // Create instances const ok = Result.Ok(42); const err = Result.Err("fail"); // Type predicates ok.is("Ok"); // true err.is("Err"); // true // Pattern matching const message = ok.match({ Ok: ({ value }) => `Value: ${value}`, Err: ({ error }) => `Error: ${error}`, }); // message === "Value: 42" ```
matchboxFactory
(
{
add: (x: number, y: number) => {
    x: number;
    y: number;
}
add
: (x: numberx: number, y: numbery: number) => ({ x: numberx, y: numbery }),
square: (x: number) => numbersquare: (x: numberx: number) => x: numberx, }, "type" );
const states: MatchboxFactory<{
    Idle: () => {};
    Done: (x: number) => {
        result: number;
    };
}, "key">
states
.
type Idle: () => MatchboxMember<"Idle", {
    Idle: () => {};
    Done: (x: number) => {
        result: number;
    };
}, "key">
Idle
().key: "Idle"key; // "Idle"
const events: MatchboxFactory<{
    add: (x: number, y: number) => {
        x: number;
        y: number;
    };
    square: (x: number) => number;
}, "type">
events
.
add: (x: number, y: number) => MatchboxMember<"add", {
    add: (x: number, y: number) => {
        x: number;
        y: number;
    };
    square: (x: number) => number;
}, "type">
add
(1, 2).type: "add"type; // "add"

Matchbox provides a powerful way to work with tagged unions in TypeScript, with additional type safety mechanisms, pattern matching, and improved developer experience.

This makes complex state modeling and data handling more robust and maintainable, with TypeScript providing excellent completion support and helping to catch errors at compile time rather than runtime.