Type-safe parsers for unknown data using neverthrow Result types.
Every parser takes an unknown input and returns a Result<T, ParseError> — no exceptions, just values.
npm install neverthrow-parse neverthrowimport{string,number,shape,arrayOf}from'neverthrow-parse'// Primitive parsingconstname=string('hello')// Ok<string>constage=number('oops')// Err<{ type: 'input_is_not_a_number', input: 'oops' }>// Object shapesconstparseUser=shape({name: string,age: number})constuser=parseUser(json)// Ok<{ name: string, age: number }> or Err with structured error// Arraysconstids=arrayOf(json,number)// Ok<number[]> or Err with index of failing itemReturns Ok<string> or Err<StringParseError>.
Returns Ok<number> or Err<NumberParseError>. Rejects NaN.
Returns Ok<bigint> or Err<BigintParseError>.
Returns Ok<boolean> or Err<BooleanParseError>.
Returns a parser that checks strict equality (===) against expected, inferring the literal type.
match('admin')('admin')// Ok<'admin'>match('admin')('user')// Err<{ type: 'input_does_not_match', input: 'user', expected: 'admin' }>Parses a JSON string. Returns Ok<JsonValue> or Err<JsonParseError>. Accepts an optional reviver function, same as JSON.parse.
string(input).andThen(json)// Ok<JsonValue> or Err<StringParseError | JsonParseError>Validates that input is a non-null, non-array object. Returns Ok<Record<PropertyKey, unknown>> or Err<ObjectParseError>.
Parses an array where every item is validated by itemParser. On failure, the error includes the index of the first failing item.
arrayOf([1,2,'x'],number)// Err<{ type: 'item_parse_error', index: 2, error: { type: 'input_is_not_a_number', ... }}>Parses an object as a typed record, validating both keys and values.
recordOf(json,{key: string,value: number})// Ok<Record<string, number>>Returns a parser that validates an object against a schema of named parsers. Infers the output type from the schema.
constparseConfig=shape({host: string,port: number})constresult=parseConfig(json)// Result<{ host: string, port: number }, ShapeParseError<...>>On failure, the error includes the key name and the nested parser error as a value_parse_error.
Every parser exports its error type (e.g. StringParseError, ShapeParseError<E>). All errors are discriminated unions with a type field, making them easy to match:
constresult=number(input)if(result.isErr()){switch(result.error.type){case'input_is_not_a_number':
// result.error.input is the original valuebreakcase'input_is_nan':
break}}