Skip to content

Type safety with Matchbox

One of the most powerful features of Matchbox is exhaustive pattern matching with the match method:

// Calculate area with pattern matching
const getArea = (shape) => shape.match({
Circle: ({ radius }) => Math.PI * radius * radius,
Rectangle: ({ width, height }) => width * height,
Triangle: ({ base, height }) => (base * height) / 2,
});
// TypeScript error if you forget a case!
const getPerimeter = (shape) => shape.match({
Circle: ({ radius }) => 2 * Math.PI * radius,
Rectangle: ({ width, height }) => 2 * (width + height),
// Error: Property 'Triangle' is missing in type '...'
});

Tagged union instances created with matchboxFactory provide automatic type narrowing with the is method:

// Create a Light matchbox with On/Off states
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
({
type Off: undefinedOff: var undefinedundefined,
type On: (percentage?: number) => {
    percentage: number;
}
On
: (percentage: numberpercentage = 100) => ({ percentage: numberpercentage }),
}); // Create light instances const
const light1: MatchboxMember<"Off", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
light1
=
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 light2: MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
light2
=
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
(75);
// Type guards with automatic type narrowing if (
const light2: MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
light2
.MatchboxMemberApi<{ Off: undefined; On: (percentage?: number) => { percentage: number; }; }, "tag">.is: <"On">(key: "On") => this is MatchboxMember<T, DataSpecs, TagProp>is("On")) {
// TypeScript knows light2.data has percentage var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without calling `require('console')`. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
@see[source](https://github.com/nodejs/node/blob/v20.11.1/lib/console.js)
console
.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
log
(`Brightness: ${
const light2: MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
light2
.
data: {
    percentage: number;
}
data
.percentage: numberpercentage}%`);
// This would be a TypeScript error: // console.log(light2.data.invalid); // Error: Property 'invalid' does not exist } // Type guards can be used in conditions function function getBrightness(light: ReturnType<typeof Light.Off> | ReturnType<typeof Light.On>): numbergetBrightness(
light: MatchboxMember<"Off", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag"> | MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
light
: type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any
Obtain the return type of a function type
ReturnType
<typeof
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
> | type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any
Obtain the return type of a function type
ReturnType
<typeof
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
>
) { if (
light: MatchboxMember<"Off", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag"> | MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
light
.MatchboxMemberApi<DataSpecs, TagProp extends string>.is: <"Off">(key: "Off") => this is MatchboxMember<T, DataSpecs, TagProp>is("Off")) {
return 0; } // TypeScript knows this must be the "On" state with percentage return
light: MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
light
.
data: {
    percentage: number;
}
data
.percentage: numberpercentage;
} var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without calling `require('console')`. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
@see[source](https://github.com/nodejs/node/blob/v20.11.1/lib/console.js)
console
.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
log
(function getBrightness(light: ReturnType<typeof Light.Off> | ReturnType<typeof Light.On>): numbergetBrightness(
const light1: MatchboxMember<"Off", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
light1
)); // 0
var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without calling `require('console')`. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
@see[source](https://github.com/nodejs/node/blob/v20.11.1/lib/console.js)
console
.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
log
(function getBrightness(light: ReturnType<typeof Light.Off> | ReturnType<typeof Light.On>): numbergetBrightness(
const light2: MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
light2
)); // 75

Use the as method for type-safe casting with runtime validation:

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";
// Create a Light matchbox with On/Off states 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
({
type Off: undefinedOff: var undefinedundefined,
type On: (percentage?: number) => {
    percentage: number;
}
On
: (percentage: numberpercentage = 100) => ({ percentage: numberpercentage }),
}); const
const light: MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
light
=
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
(80);
// Safe casting with runtime validation try { // This works because light is actually in the "On" state const
const asOn: MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
asOn
=
const light: MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
light
.
MatchboxMemberApi<{ Off: undefined; On: (percentage?: number) => { percentage: number; }; }, "tag">.as: <"On">(key: "On") => MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
as
("On");
var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without calling `require('console')`. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
@see[source](https://github.com/nodejs/node/blob/v20.11.1/lib/console.js)
console
.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
log
(`Brightness: ${
const asOn: MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
asOn
.
data: {
    percentage: number;
}
data
.percentage: numberpercentage}%`); // Works fine: "Brightness: 80%"
// This will throw because light is not in the "Off" state const
const asOff: MatchboxMember<"Off", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
asOff
=
const light: MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
light
.
MatchboxMemberApi<{ Off: undefined; On: (percentage?: number) => { percentage: number; }; }, "tag">.as: <"Off">(key: "Off") => MatchboxMember<"Off", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
as
("Off");
var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without calling `require('console')`. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
@see[source](https://github.com/nodejs/node/blob/v20.11.1/lib/console.js)
console
.Console.log(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stdout` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const count = 5; console.log('count: %d', count); // Prints: count: 5, to stdout console.log('count:', count); // Prints: count: 5, to stdout ``` See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
log
("This line will never execute",
const asOff: MatchboxMember<"Off", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
asOff
);
} catch (var e: anye: any) { var console: Console
The `console` module provides a simple debugging console that is similar to the JavaScript console mechanism provided by web browsers. The module exports two specific components: * A `Console` class with methods such as `console.log()`, `console.error()` and `console.warn()` that can be used to write to any Node.js stream. * A global `console` instance configured to write to [`process.stdout`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstdout) and [`process.stderr`](https://nodejs.org/docs/latest-v20.x/api/process.html#processstderr). The global `console` can be used without calling `require('console')`. _**Warning**_: The global console object's methods are neither consistently synchronous like the browser APIs they resemble, nor are they consistently asynchronous like all other Node.js streams. See the [`note on process I/O`](https://nodejs.org/docs/latest-v20.x/api/process.html#a-note-on-process-io) for more information. Example using the global `console`: ```js console.log('hello world'); // Prints: hello world, to stdout console.log('hello %s', 'world'); // Prints: hello world, to stdout console.error(new Error('Whoops, something bad happened')); // Prints error message and stack trace to stderr: // Error: Whoops, something bad happened // at [eval]:5:15 // at Script.runInThisContext (node:vm:132:18) // at Object.runInThisContext (node:vm:309:38) // at node:internal/process/execution:77:19 // at [eval]-wrapper:6:22 // at evalScript (node:internal/process/execution:76:60) // at node:internal/main/eval_string:23:3 const name = 'Will Robinson'; console.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to stderr ``` Example using the `Console` class: ```js const out = getStreamSomehow(); const err = getStreamSomehow(); const myConsole = new console.Console(out, err); myConsole.log('hello world'); // Prints: hello world, to out myConsole.log('hello %s', 'world'); // Prints: hello world, to out myConsole.error(new Error('Whoops, something bad happened')); // Prints: [Error: Whoops, something bad happened], to err const name = 'Will Robinson'; myConsole.warn(`Danger ${name}! Danger!`); // Prints: Danger Will Robinson! Danger!, to err ```
@see[source](https://github.com/nodejs/node/blob/v20.11.1/lib/console.js)
console
.Console.error(message?: any, ...optionalParams: any[]): void (+1 overload)
Prints to `stderr` with newline. Multiple arguments can be passed, with the first used as the primary message and all additional used as substitution values similar to [`printf(3)`](http://man7.org/linux/man-pages/man3/printf.3.html) (the arguments are all passed to [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args)). ```js const code = 5; console.error('error #%d', code); // Prints: error #5, to stderr console.error('error', code); // Prints: error 5, to stderr ``` If formatting elements (e.g. `%d`) are not found in the first string then [`util.inspect()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilinspectobject-options) is called on each argument and the resulting string values are concatenated. See [`util.format()`](https://nodejs.org/docs/latest-v20.x/api/util.html#utilformatformat-args) for more information.
@sincev0.1.100
error
("Cast failed:", var e: anye.message); // "Attempted to cast On as Off"
} // Practical example: only adjust brightness for "On" lights export function
function adjustBrightness(light: ReturnType<typeof Light.Off> | ReturnType<typeof Light.On>, adjustment: number): MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag"> | MatchboxMember<...>
adjustBrightness
(
light: MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag"> | MatchboxMember<"Off", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
light
: type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any
Obtain the return type of a function type
ReturnType
<typeof
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
> | type ReturnType<T extends (...args: any) => any> = T extends (...args: any) => infer R ? R : any
Obtain the return type of a function type
ReturnType
<typeof
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
>,
adjustment: numberadjustment: number ) { try { // Try to cast to "On" state const
const onLight: MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
onLight
=
light: MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag"> | MatchboxMember<"Off", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
light
.
MatchboxMemberApi<DataSpecs, TagProp extends string>.as: <"On">(key: "On") => MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
as
("On");
// If successful, create a new light with adjusted brightness const const newBrightness: numbernewBrightness = var Math: Math
An intrinsic object that provides basic mathematics functionality and constants.
Math
.Math.max(...values: number[]): number
Returns the larger of a set of supplied numeric expressions.
@paramvalues Numeric expressions to be evaluated.
max
(
0, var Math: Math
An intrinsic object that provides basic mathematics functionality and constants.
Math
.Math.min(...values: number[]): number
Returns the smaller of a set of supplied numeric expressions.
@paramvalues Numeric expressions to be evaluated.
min
(100,
const onLight: MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
onLight
.
data: {
    percentage: number;
}
data
.percentage: numberpercentage + adjustment: numberadjustment)
); return
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
(const newBrightness: numbernewBrightness);
} catch { // Light is off, return it unchanged return
light: MatchboxMember<"On", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag"> | MatchboxMember<"Off", {
    Off: undefined;
    On: (percentage?: number) => {
        percentage: number;
    };
}, "tag">
light
;
} }

Matchina also provides filter functions for more complex type guards:

import { matchbox, withKey, withData } from "matchina";
// ---cut---
const Shape = matchbox({
Circle: (radius: number, color: string = "black") => ({ radius, color }),
Rectangle: (width: number, height: number, color: string = "black") => ({
width,
height,
color,
}),
Triangle: (base: number, height: number, color: string = "black") => ({
base,
height,
color,
}),
});
const shapes = [
Shape.Circle(5, "red"),
Shape.Rectangle(10, 20, "blue"),
Shape.Circle(8, "green"),
Shape.Triangle(15, 10, "red"),
];
// Filter by key
const circles = shapes.filter(withKey("Circle"));
console.log(`Found ${circles.length} circles`);
// Filter by data property
const redShapes = shapes.filter(withData((data) => data.color === "red"));
console.log(`Found ${redShapes.length} red shapes`);
// Combine filters
const largeCircles = shapes.filter(
(shape) => shape.is("Circle") && shape.data.radius > 7,
);
console.log(`Found ${largeCircles.length} large circles`);
  • Type safety: Prevent runtime errors by catching type mismatches at compile time
  • Code completion: Get proper IDE suggestions based on narrowed types
  • Refactoring safety: When you change a state’s structure, TypeScript will flag all places that need updates
  • Exhaustive checking: Ensure all possible states are handled with pattern matching

Now that you understand type guards, explore these related guides: