An open API service indexing awesome lists of open source software.

https://github.com/flix-tech/fp-ts-type-check

runtime type validation library for Typescript
https://github.com/flix-tech/fp-ts-type-check

hacktoberfest parsers typescript

Last synced: over 1 year ago
JSON representation

runtime type validation library for Typescript

Awesome Lists containing this project

README

          

fp-ts-type-check is a library for runtime type validation of variables where you can't say their type for sure i.e. data you get via some API. It's somewhat similar to Typescript's [Type Guards](https://www.typescriptlang.org/docs/handbook/advanced-types.html#user-defined-type-guards) except it uses type system to make sure this data is properly validated.

Features:

* **Type safe.** Typescript compiler makes sure your types and your type checkers are always in sync.
* **Detailed error reports.** If parsing of a big deep-nested structure failed - you'll know where exactly in that structure you have invalid data and why it was considered invalid
* **Composable.** Type checkers for big structures are created by composing checkers for simple structures.
* **Functional.** Each type checker is a pure function returning `Either` type from fp-ts. It's up for you to decide how to handle errors.
* **[Tree-shakeable](https://webpack.js.org/guides/tree-shaking/).** Bundle only functions you really use.

## Installation

To install the stable version:

```
npm install '@flix-tech/fp-ts-type-check@~0.2.0'
```

While the major version number is 0 changes in minor version number bay break backward compatibility so you should stick to a fixed minor version.

## Usage

Meet `Parser[T]`, the main type of this library. `Parser[T]` is a function that takes any variable and checks if it's a variable of type `T`. It either returns the same value as `T` or `ParseError` object with parse error details. Parser's type definition looks somewhat like this:

```typescript
type Parser = (x: unknown): Either;

interface ParseError {
path: string; // Path to the property causing error in deep nested structures
message: string; // Parsing error message
}
```

We're using the type [Either](https://gcanti.github.io/fp-ts/modules/Either.ts.html) from [fp-ts](https://github.com/gcanti/fp-ts) library.

Parsers for some complex structures you'd want to validate are composed from small parsers like here:

```typescript
import * as P from 'fp-ts-type-check';

interface ShoppingListItem {
name: string;
amount: { count: number; unit?: string };
}
const shoppingListItemParser: P.Parser = P.type({
name: P.string,
amount: P.type({
count: P.number,
unit: P.optional(P.string),
}),
});

shoppingListItem({name: "Apple", amount: {count: 5}}); // Right({name: "Apple", amount: {count: 5}})

shoppingListItem({name: "Apple", amount: {count: "some"}}); // Left({path: ".amount.count", message: "expected number, got string"})
```

As you can see, `ParseError` data is for your eyes only, user should get a generalized error message appropriate in this case.

You can reuse your parsers to construct parsers for even bigger structures:

```typescript
type ShoppingList = array;

const shoppingListParser: P.Parser = P.arrayOf(shoppingListItemParser);

const validShoppingList = [
{name: "Apple", amount: {count: 5}},
{name: "Milk", amount: {count: 500, unit: 'ml'}},
];
shoppingListParser(validShoppingList); // Right(...)

const invalidShoppingList = [
{name: "Apple", amount: {count: 5}},
{name: "Milk", amount: {unit: 'ml'}}, // No count here
];
shoppingListParser(invalidShoppingList); // Left({path: "[1].amount.count", message: "expected number, got undefined"})
```

# API documentation

### Simple type parsers

* `string(): Parser` - checks that value is string.
* `boolean(): Parser` - checks that value is boolean.
* `number(): Parser` - checks that value is number.
* `object(): Parser` - checks that value is any object.
* `any(): Parser` - does not check anything.
* `exact
(expected: A): Parser` - checks that value is same as expected one.
* `oneOf
(allowed: A[]): Parser` - checks that value is one of allowed ones.
* `keyOf
(allowed: A): Parser` - checks that value is string and also is a key of object `allowed`.

## Copositional parsers

* `type(propertyParsers: { [K in keyof A]: Parser }): Parser` - checks that values is an object and validates each it's property with corresponding parser.

* `arrayOf(parseBody: Parser): Parser` - checks that value is an array and every item matches `parseBody` parser.

* `optional(parseBody: Parser): Parser` - checks that value is either undefined or matches `parseBody` parser.

* `nullable(parseBody: Parser): Parser` - checks that value is either null or matches `parseBody` parser.

* `discriminatedUnion(parsers: {(type value): (type parser)}): Parser` - checks that value is a [discriminated union](https://www.typescriptlang.org/docs/handbook/advanced-types.html#discriminated-unions) with discriminant in `type` property. Example usage:

```typescript
type Foo = { type: 'foo'; foo: number };
type Bar = { type: 'bar'; bar: number };
type FooBar = Foo | Bar;

const parser: P.Parser = P.discriminatedUnion({
foo: P.type({ foo: P.number }),
bar: P.type({ bar: P.number }),
});
```

### Logic combination parsers

* `and(parserA: Parser, parserB): Parser` - checks that value matches both types A and B.
* `or(parserA: Parser
, parserB): Parser` - checks that value matches any of types A or B.

## License

The MIT License (MIT)