Skip to content

Pattern Matching

Given the following matchbox factory:

export const shapes = matchboxFactory({
Circle: (radius: number) => ({ radius }),
Square: (side: number) => ({ side }),
Rectangle: (width: number, height: number) => ({ width, height }),
});

The most powerful feature of tagged unions created with matchboxFactory is exhaustive pattern matching with the match method:

export const const area: numberarea = 
const someShape: MatchboxMember<"Circle", {
    Circle: (radius: number) => {
        radius: number;
    };
    Square: (side: number) => {
        side: number;
    };
    Rectangle: (width: number, height: number) => {
        width: number;
        height: number;
    };
}, "type">
someShape
.
MatchboxMemberApi<{ Circle: (radius: number) => { radius: number; }; Square: (side: number) => { side: number; }; Rectangle: (width: number, height: number) => { width: number; height: number; }; }, "type">.match<number>(cases: MatchCases<{
    Circle: (radius: number) => {
        radius: number;
    };
    Square: (side: number) => {
        side: number;
    };
    Rectangle: (width: number, height: number) => {
        width: number;
        height: number;
    };
}, number, true>, exhaustive?: boolean): number (+1 overload)
match
({
type Circle: ({ radius }: {
    radius: number;
}) => number
Circle
: ({ radius: numberradius }) => var Math: Math
An intrinsic object that provides basic mathematics functionality and constants.
Math
.Math.PI: number
Pi. This is the ratio of the circumference of a circle to its diameter.
PI
* radius: numberradius * radius: numberradius,
type Square: ({ side }: {
    side: number;
}) => number
Square
: ({ side: numberside }) => side: numberside * side: numberside,
type Rectangle: ({ width, height }: {
    width: number;
    height: number;
}) => number
Rectangle
: ({ width: numberwidth, height: numberheight }) => width: numberwidth * height: numberheight,
});

Sometimes you want to handle multiple states with a single case, or provide a fallback:

export const const cornerCount: numbercornerCount = 
const someShape: MatchboxMember<"Circle", {
    Circle: (radius: number) => {
        radius: number;
    };
    Square: (side: number) => {
        side: number;
    };
    Rectangle: (width: number, height: number) => {
        width: number;
        height: number;
    };
}, "type">
someShape
.
MatchboxMemberApi<{ Circle: (radius: number) => { radius: number; }; Square: (side: number) => { side: number; }; Rectangle: (width: number, height: number) => { width: number; height: number; }; }, "type">.match<number>(cases: MatchCases<{
    Circle: (radius: number) => {
        radius: number;
    };
    Square: (side: number) => {
        side: number;
    };
    Rectangle: (width: number, height: number) => {
        width: number;
        height: number;
    };
}, number, true>, exhaustive?: boolean): number (+1 overload)
match
({
type Circle: () => numberCircle: () => 0, _?: ((...args: any[]) => number) | undefined_: () => 4, // Default case for Square and Rectangle });

You can opt-out of exhaustiveness checking by passing false as the second argument:

export const const optionalNickname: stringoptionalNickname = 
const someShape: MatchboxMember<"Circle", {
    Circle: (radius: number) => {
        radius: number;
    };
    Square: (side: number) => {
        side: number;
    };
    Rectangle: (width: number, height: number) => {
        width: number;
        height: number;
    };
}, "type">
someShape
.
MatchboxMemberApi<{ Circle: (radius: number) => { radius: number; }; Square: (side: number) => { side: number; }; Rectangle: (width: number, height: number) => { width: number; height: number; }; }, "type">.match<string>(cases: MatchCases<{
    Circle: (radius: number) => {
        radius: number;
    };
    Square: (side: number) => {
        side: number;
    };
    Rectangle: (width: number, height: number) => {
        width: number;
        height: number;
    };
}, string, true>, exhaustive?: boolean): string (+1 overload)
match
(
{
type Circle: ({ radius }: {
    radius: number;
}) => string
Circle
: ({ radius: numberradius }) => `Circle with radius ${radius: numberradius}`,
type Square: ({ side }: {
    side: number;
}) => string
Square
: ({ side: numberside }) => `Square with side ${side: numberside}`,
}, false );