> TODO: description

Usage no npm install needed!

<script type="module">
  import fractureParse from 'https://cdn.skypack.dev/@fracture/parse';


@fracture/parser Parser for TypeScript

A delarative, composable library of JSON compatible value parsers.


npm install @fracture/parse


The gist: Parser<O,I> is a function that takes a type I in as its single argument and returns a Result<O,I>.

Result<O,I> is a union of Success<O>|Failure<I> which are container types that describe the success and failure branches of the Parser<O,I> logic.

This library was designed to be used with values returne from JSON.parse.

A basic JSON parser:

const parseJSON: Parser<any,any> = (input) => {
    try {
        return success(JSON.parse(input);
    } catch (error) {
        return failure(error.message, input);

Parser<any,any> is not exactly useful when the goal is type safety. This library provides the building blocks to validate ad return JSON primitives and combinations of them.

Utility functios

A set of functions to simplify working with Result<O,I> types.


isSuccess is a guard function that refines a Result<O,I> to Success<O>.

const result = parseString(1);

if (isSuccess(result)) {
    const value = result.value; // value _is_ a `string`


isFailure is the logical inverse of isSuccess and refines the Failure<I> branch of a Result<O,I>:

const result = parseString('maybe a string');

if (isFailure(result)) {
    throw new Error(result.message);


value unwraps the boxed value of Success<T>. Allows the shape of Success<T> to be opaque to the user of this api.

const result = parseString('maybe a string');
if (isSuccess(result)) {
    const theString = value(result);


Bulids a Success<T> result case:

const parseInteger: Parser<any, number> = (maybeNumber) => {
    const int = parseInt(maybeNumber);
    return int === maybeNumber
        ? success(int)
        : failure(`${maybeNumber} not an int`, maybeNumber);


Builds a Failure<T> result case:

const parsePositive: Parser<any, number> = (maybeNumber) => {
    return typeof maybeNumber === 'number' && maybeNumber > 0
        ? success(maybeNumber)
        : failure(`${maybeNumber} not a posistive number`, maybeNumber);

Base Parsers

A set of parsers for non-container JSON literals that can be used to build more complex parsers.

  • parseString is Parser<any, string>
  • parseNumber is `Parser<any, number>
  • parseUndefined is Parser<any, undefined>
  • parseNull is Parser<any, null>
  • parseBoolean is Parser<any, boolean>
const result = parseString(("maybe a string": any));

if (isFailure(result)) {
    throw new Error(result.reason);

const strValue = value(result);

Parser Combinators

Combinators that combine parsers into more complex parsers.


parseObjectOf accepts key/value pairs of parsers and parses the key/value pairs of the value it receives.

const parsePerson = parseObjectOf({
    name: parseString,
    age: parseNumber,
    metInPerson: parseBoolean

const result = parsePerson({});

if (isFailure(result)) {
    throw new Error(result.reason);

const person = value(result);

// TypeScript knows person.name is a `string`.
console.log(`Hello ${person.name}`);
// TypeScript knows person.age is a `number`.
console.log(`Maybe born in`, (new Date()).getYear() - person.age);


For parsing values of type Array<T>.

Given any Parser<O,I>, succeeds when the input:

  1. is an Array
  2. each member of the Array succeeds the provider Parser<O,I>

parseArrayOf accepts a Parser<O,I> and returns a Parser<I, Array<O>>.

const parsePeople = parseArrayOf(parsePerson);

// Result<any, Array<{name: string, age: number, metInPerson: boolean}>>
const result = parsePeople(JSON.parse(someString));


For parsing values of type {[string]: T}.

Given a Parser<any, T> the returned parser succeeds when:

  1. The value is an indexed object
  2. Each member of the indexed object succeeds the provider Parser<any, T>
// An object that is an index of users, indexed by a string value
const parseUuser = parseObjectOf({username: parseString});
const parseUserIndex = parseIndexedObjectOf(parseUser);


Builds a parser that succeeds when the input is exactly equal to the provided value.

const parse = parseExactly('shipped');

const result = parse('pending');

if (isSuccess(result)) {
    const shipped: 'shipped' = result.value;


Allows one of a list of parsers to succeed. Useful for parsing an enumeration of known values.

const parseStatus = parseOneOf(

// Result<any, 'published'|'draft'>
const result = parseStatus('other');


Given any parser, returns a new parser that succeds when original parser succeeds or the value is null.

const parse = optional(parseString);

// Result<any, (null|string)>
const result = parse(null);


Given any parser, returns a new parser that succeeds when the original parser succeeds or the value is undefined.

const parse = voidable(parseString);

// Result<any, (undefined|string)>
const result = parse(undefined);

Complex Example

import {
} from 'parser';

const parseAuthor = parseObjectOf({
    username: parseString,
    avatar: optional(parseString),

const parsePost = parseObjectOf(
    title: parseString,
    status: parseOneOf(
    author: parseAuthor,
    // https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Date/parse
    publishedAt: mapParser(
        // assuming ISO8601 string
        string => success(new Date(string))

 * Expects JSON like:
 * ```
 * {"posts": [...Post]}
 * ```
const parseResponse = parseObjectOf({
    posts: parseArrayOf( parsePost )

 * Chained with DOM fetch
async function getPosts() {
    const response = await fetch('/api/site/awesome.blog/posts')
        .then(response => response.json())

     * Type guard to unwrap the parsed value
    if (isSuccess(response)) {
        // 🚀 The response was successfully parsed and is safely typed
        const postResponse = response.value;
    throw new Error(response.reason);

// Use the types created by the parsers:

type Author = ParserType<typeof parseAuthor>;
type Post = ParserType<typeof parsePost>;

const author: Author = {
   username: 5, // 💥 Not a string!

const post: Post = {
    title: 'Hello World',
    status: 'other', // 💥 Not 'published' or 'draft'
    publishedAt: 1235500482, // 💥 Not a Date