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
- Host: GitHub
- URL: https://github.com/flix-tech/fp-ts-type-check
- Owner: flix-tech
- License: mit
- Created: 2020-08-04T14:38:52.000Z (about 6 years ago)
- Default Branch: master
- Last Pushed: 2021-04-07T13:42:39.000Z (over 5 years ago)
- Last Synced: 2025-03-17T22:56:47.805Z (over 1 year ago)
- Topics: hacktoberfest, parsers, typescript
- Language: TypeScript
- Homepage:
- Size: 79.1 KB
- Stars: 15
- Watchers: 3
- Forks: 0
- Open Issues: 0
-
Metadata Files:
- Readme: README.md
- License: LICENSE
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)