Skip to content

Type-Safe State Matchina

Build strongly-typed state machines with powerful pattern matching
const 
const states: StateMatchboxFactory<{
    Fee: undefined;
    Fi: () => {};
    Fo: (name: string) => {
        name: string;
    };
    Fum: (name: string, age: number) => {
        name: string;
        age: number;
    };
}>
states
=
defineStates<{
    Fee: undefined;
    Fi: () => {};
    Fo: (name: string) => {
        name: string;
    };
    Fum: (name: string, age: number) => {
        name: string;
        age: number;
    };
}>(config: {
    Fee: undefined;
    Fi: () => {};
    Fo: (name: string) => {
        name: string;
    };
    Fum: (name: string, age: number) => {
        name: string;
        age: number;
    };
}): StateMatchboxFactory<{
    Fee: undefined;
    Fi: () => {};
    Fo: (name: string) => {
        name: string;
    };
    Fum: (name: string, age: number) => {
        name: string;
        age: number;
    };
}>
`defineStates` creates a type-safe state factory for your state machine. Each key in the config becomes a state constructor, inferring parameters and data shape. Usage: ```ts const states = defineStates({ SomeEmptyState: undefined, // No parameters SomeValueState: "any value here" || 42, // Any value as data SomeStateWithCreate: (...anyParameters) => ({ ...anyPayload }), }); // Usage states.SomeEmptyState().key; // "SomeEmptyState" states.SomeValueState().data; // "any value here" || 42 states.SomeStateWithCreate("param1", "param2").data; // { ...anyPayload } ``` Type benefits: - State keys and data are fully inferred - Pattern matching and type guards are available - Exhaustive match on state keys
@example```typescript const states = defineStates({ Idle: undefined, Loading: (query: string) => ({ query }), Success: (query: string, results: string[]) => ({ query, results }), Error: (query: string, message: string) => ({ query, message }), }); // Usage: states.Idle().key // "Idle" states.Loading("search").data // { query: "search" } states.Success("search", ["a", "b"]).data // { query, results } ```
defineStates
({
type Fee: undefinedFee: var undefinedundefined, type Fi: () => {}Fi: () => ({}),
type Fo: (name: string) => {
    name: string;
}
Fo
: (name: stringname: string) => ({ name: stringname }),
type Fum: (name: string, age: number) => {
    name: string;
    age: number;
}
Fum
: (name: stringname: string, age: numberage: number) => ({ name: stringname, age: numberage }),
}); const
const fo: StateMatchbox<"Fo", {
    Fee: undefined;
    Fi: () => {};
    Fo: (name: string) => {
        name: string;
    };
    Fum: (name: string, age: number) => {
        name: string;
        age: number;
    };
}>
fo
=
const states: StateMatchboxFactory<{
    Fee: undefined;
    Fi: () => {};
    Fo: (name: string) => {
        name: string;
    };
    Fum: (name: string, age: number) => {
        name: string;
        age: number;
    };
}>
states
.F
  • Fee
  • Fi
  • Fo
  • Fum
type Fo: (name: string) => StateMatchbox<"Fo", {
    Fee: undefined;
    Fi: () => {};
    Fo: (name: string) => {
        name: string;
    };
    Fum: (name: string, age: number) => {
        name: string;
        age: number;
    };
}>
o
("John");
const fo: StateMatchbox<"Fo", {
    Fee: undefined;
    Fi: () => {};
    Fo: (name: string) => {
        name: string;
    };
    Fum: (name: string, age: number) => {
        name: string;
        age: number;
    };
}>
fo
.key: "Fo"key; // "Fo"
const fo: StateMatchbox<"Fo", {
    Fee: undefined;
    Fi: () => {};
    Fo: (name: string) => {
        name: string;
    };
    Fum: (name: string, age: number) => {
        name: string;
        age: number;
    };
}>
fo
.MatchboxMemberApi<{ Fee: undefined; Fi: () => {}; Fo: (name: string) => { name: string; }; Fum: (name: string, age: number) => { name: string; age: number; }; }, "key">.is: <"Fo">(key: "Fo") => this is MatchboxMember<T, DataSpecs, TagProp>is("Fo"); // true
const fo: StateMatchbox<"Fo", {
    Fee: undefined;
    Fi: () => {};
    Fo: (name: string) => {
        name: string;
    };
    Fum: (name: string, age: number) => {
        name: string;
        age: number;
    };
}>
fo
.
data: {
    name: string;
}
data
; // { name: "John" }
export const { const name: stringname } =
const fo: StateMatchbox<"Fo", {
    Fee: undefined;
    Fi: () => {};
    Fo: (name: string) => {
        name: string;
    };
    Fum: (name: string, age: number) => {
        name: string;
        age: number;
    };
}>
fo
.
data: {
    name: string;
}
data
; // { name: "John" }
export const { const age: numberage } =
const states: StateMatchboxFactory<{
    Fee: undefined;
    Fi: () => {};
    Fo: (name: string) => {
        name: string;
    };
    Fum: (name: string, age: number) => {
        name: string;
        age: number;
    };
}>
states
.
type Fum: (name: string, age: number) => StateMatchbox<"Fum", {
    Fee: undefined;
    Fi: () => {};
    Fo: (name: string) => {
        name: string;
    };
    Fum: (name: string, age: number) => {
        name: string;
        age: number;
    };
}>
Fum
("Jane", 30).
data: {
    name: string;
    age: number;
}
data
; // { name: "Jane", age: 30 }
Terminal window
npm install matchina