GithubHelp home page GithubHelp logo

gillchristian / io-ts-reporters Goto Github PK

View Code? Open in Web Editor NEW
89.0 2.0 16.0 708 KB

Error reporters for io-ts

Home Page: https://gillchristian.github.io/io-ts-reporters

License: MIT License

TypeScript 96.84% JavaScript 3.16%
validation io-ts fp-ts type-safety

io-ts-reporters's Introduction

io-ts-reporters

Error reporters for io-ts.

scarf-downloads

Currently this package only includes one reporter. The output is an array of strings in the format of:

Expecting ${expectedType} at ${path} but instead got: ${actualValue}

And for union types:

Expecting one of:
    ${unionType1}
    ${unionType2}
    ${...}
    ${unionTypeN}
at ${path} but instead got: ${actualValue}

Installation

yarn add io-ts-reporters

Example

import * as t from 'io-ts'
import reporter from 'io-ts-reporters'

const User = t.interface({name: t.string})

// When decoding fails, the errors are reported
reporter.report(User.decode({nam: 'Jane'}))
//=> ['Expecting string at name but instead got: undefined']

// Nothing gets reported on success
reporter.report(User.decode({name: 'Jane'}))
//=> []

To only format the validation errors in case the validation failed (ie. mapLeft) use formatValidationErrors instead.

import * as t from 'io-ts'
import {formatValidationErrors} from 'io-ts-reporters'
import * as E from 'fp-ts/Either'
import {pipe} from 'fp-ts/pipeable'

const User = t.interface({name: t.string})

const result = User.decode({nam: 'Jane'}) // Either<t.Errors, User>

E.mapLeft(formatValidationErrors)(result) // Either<string[], User>

For more examples see the tests.

TypeScript compatibility

io-ts-reporters version required typescript version
1.0.0 3.5+
<= 0.0.21 2.7+

Testing

yarn
yarn run test

Credits

This library was created by OliverJAsh.

io-ts-reporters's People

Contributors

bmcniel avatar dderevjanik avatar denisfrezzato avatar dependabot[bot] avatar gillchristian avatar lo1tuma avatar oliverjash avatar osdiab avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar

io-ts-reporters's Issues

Include codec name in reports

with long codec errors (mitigated by #32 ) it's often hard to tell which codec exactly was erroring - would be nice if a codec name was in the message, if present

Large bundle size

When using my fork or io-ts-reporters which is just tracking master, the bundle size is much larger than it ought to be. This showed up on the project I am using it on.

https://bundlephobia.com/result?p=@osdiab/[email protected]

This library can potentially make use of tree shaking or something to avoid bundling the entirety of io-ts and fp-ts with it. Maybe:

  • sideEffects: false in package.json
  • ESModules as an output option
  • maybe a bundler like Rollup can help
  • would having those as peer dependencies be a good idea?

Change reporter to io-ts Reporter

To follow io-ts "standard" for reporters we should update the reporter to match the Reporter interface

And also remove the default export in favor of the named one (reporter would be what is now prettyReporter)

/**
* Deprecated, use the default export instead.
*
* @category deprecated
* @deprecated
* @since 1.0.0
*/
export const reporter = <T>(validation: t.Validation<T>) =>
pipe(
validation,
E.mapLeft(formatValidationErrors),
E.fold(
errors => errors,
() => []
)
);
const prettyReporter: Reporter<string[]> = { report: reporter };
export default prettyReporter;

NOTE: this would be a breaking change

Hard to debug union types

Hello,

I have created a webpackbin to illustrate the problem. If union is not used, the reporter shows the problem exactly, if not, it just prints the whole expected type and provided value.

Check the console on webpackbin to see what I mean

Use Elm format

Elm sets a really good example of friendly messages for validation (decode) errors:

import Json.Decode exposing (..)

decodeString (list (list int)) "[ [0], [1,2,3], [4,5] ]"
-- Ok [[0],[1,2,3],[4,5]] : Result.Result String (List (List Int))

decodeString (list (list int)) "f"
-- Err "Given an invalid JSON: Unexpected end of input"
--     : Result.Result String (List (List Int))

decodeString (list (list int)) "{}"
-- Err "Expecting a List but instead got: {}"
--     : Result.Result String (List (List Int))

decodeString (list (list int)) "[[{}]]"
-- Err "Expecting an Int at _[0][0] but instead got: {}"
--     : Result.Result String (List (List Int))

decodeString (list (field "foo" int)) "[{ \"foo\": 1 },{ \"foo\": {} }]"
-- Err "Expecting an Int at _[1].foo but instead got: {}"
--     : Result.Result String (List Int)

decodeString (list (field "bar" string)) "[{}]"
-- Err "Expecting an object with a field named `bar` at _[0] but instead got: {}"
--     : Result.Result String (List String)

type alias Point = { x : Int, y : Int }
pointDecoder = map2 Point (field "x" int) (field "y" int)
-- <decoder> : Json.Decode.Decoder Repl.Point
decodeString pointDecoder  """{ "x": 3, "y": 4 }"""
-- Ok { x = 3, y = 4 } : Result.Result String Repl.Point
decodeString pointDecoder """{ "z": 3, "f": 4 }"""
-- Err "Expecting an object with a field named `x` but instead got: {\"z\":3,\"f\":4}"
--     : Result.Result String Repl.Point

References

To do

  • JSON.stringify value instead of .toString, e.g. {} instead of [object Object].

Is it possible to report Either<DecodeError, A>

Hello,
I am using [email protected] and [email protected], but I cannot report an error for decode responses such as Either<DecodeError, A>. This is an example where I want to use the report instead of a raw error.

import * as D from 'io-ts/Decoder';
import { pipe } from 'fp-ts/function';
import { fold } from 'fp-ts/Either';

export function decode<A>(input: unknown, decoder: D.Decoder<unknown, A>): A {
    return pipe(
        decoder.decode(input),
        fold(
            (errors) => {
                throw new Error(JSON.stringify(errors)); // Here I want to use the reporter.
            },
            (value: A) => value,
        ),
    );
}

Are you planning to support the D.DecodeError for reporting?

UglifyJS build Error

Hi,
I'm getting this error when trying to build an app:

C:\PATH_TO_PROJECT\webpack\build.js:35
                        throw new _gulpUtil2.default.PluginError('webpack', buildError);
                        ^
Error: app-3333a2162c4f3c125228.js from UglifyJs
Unexpected token: operator (>) [C:/PATH_TO_PROJECT/node_modules/io-ts-reporters/target/src/index.js:5,0][app-3333a2162c4f3c125228.js:273839,28]

I'm using node 8.X.Y , babel 6.23.0 and building using gulp, which is calling a webpack. In dev mode there is no error and working as it supposed to.

Not sure, what causing this error, but setting "target": "es5" in tsconfig.json can fix this error.

Update dependencies

Update the dependencies to the latest

  • TypeScript
  • fp-ts
  • io-ts

And then enable Dependabot

Remove exports needed for emitting TypeScript declarations

Hi,

I noticed the following comment in the source code

// These are only needed for emitting TypeScript declarations

It seems that with a couple of changes they are no more needed

import { Validation, ValidationError } from 'io-ts';
import * as array from 'fp-ts/lib/Array';
import { Option } from 'fp-ts/lib/Option';

const jsToString = (value: any) => (
    value === undefined
        ? 'undefined'
        : JSON.stringify(value)
);

export function formatValidationError(error: ValidationError): Option<string> {
    const path = error.context
        .map(c => c.key)
        // The context entry with an empty key is the original type ("default
        // context"), not an type error.
        .filter(key => key.length > 0)
        .join('.');

    // The actual error is last in context
    const maybeErrorContext = array.last(error.context);

    return maybeErrorContext.map(errorContext => {
        const expectedType = errorContext.type.name;
        return (
            // tslint:disable-next-line max-line-length
            // https://github.com/elm-lang/core/blob/18c9e84e975ed22649888bfad15d1efdb0128ab2/src/Native/Json.js#L199
            `Expecting ${expectedType}`
            + (path === '' ? '' : ` at ${path}`)
            + ` but instead got: ${jsToString(error.value)}.`
        );
    });
}

export function reporter(validation: Validation<any>): Array<string> {
    return validation.fold(
        errors => (
            array.catOptions(
                errors.map(formatValidationError),
            )
        ),
        () => [],
    );
}

Also, only the Array module is imported (instead of the whole fp library)

Handle empty/root path

If the type error as at the root, path comes back as empty string, resulting in:

Expected type of  to be …

Intelligently select branches/depth to describe in union types

In combination with #38 , if this reporter could intelligently select a path to display errors for and skip errors/reporting more deeply if the message is getting overwhelmingly long - I think it would make errors easier to grok. Perhaps this truncating behavior ought to be behind a flag or exported separately for people who want full errors.

Basic example

Decode error for FeedItem: expected one of:
  - UserSuggestionFeedItem
  - UserPostFeedItem
  - PageSuggestionFeedItem
but instead got undefined.

More complex example


Decode error for FeedItem: expected one of:
  - UserSuggestionFeedItem
  - UserPostFeedItem
  - PageSuggestionFeedItem
  - { type: "GroupFeedItem", name: string, meta: { ... }, ... }
but value didn't match. Errors for closest match, UserPostFeedItem:
  - Expected number at data.numLikes but instead got: "4"
  - Expected Date at data.meta.postedAt but instead got: undefined.
  - Expected PostType at data.postType but instead got: "Omar Diab"
  ... and 4 other errors ...

Would potentially be able to be more specific for tagged types.

Implement a reporter with suggestions

Current reporter

import * as t from 'io-ts';
import Reporter from 'io-ts-reporters';

const User = t.interface({ name: t.string });

Reporter.report(User.decode({ nam: 'Jane' })); 

The reported error from that example would be:

Expecting string at name but instead got: undefined

This is good for usage on an error aggregator (eg. honeybadger.io) where you just want to know what went wrong.

An smarter reporter

But there could be an use case for an smarter reporter that would also give suggestions.

Specially because, although the reporter error on the example is correct by saying name property was not provided. It is also obvious (to a human) that it wasn't provided because there's a typo (ie. the object does have a very similar property that even matches the expected type of the value).

A good inspiration could be Elm's error messages.

For the following code

type alias Model = { name : String, password : String }

init : Model
init = { nam = "", password = "" }

The error message is:

-- TYPE MISMATCH ----------------------------------------------- Jump To Problem

Something is off with the body of the `init` definition:

33|   { nam = "", password = "" }
      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
The body is a record of type:

    { nam : String, password : String }

But the type annotation on `init` says it should be:

    Model

Hint: Seems like a record field typo. Maybe nam should be name?

Hint: Can more type annotations be added? Type annotations always help me give
more specific messages, and I think they could help a lot in this case!

About use cases

Since io-ts is meant for runtime validation I am not sure if this is something that would be used as much as the "regular" reporter.

Changelog?

It looks like a new major version was released – are there release notes published anywhere?

Error after updating to Typescript 2.7

Hi, after updating to Typescript 2.7 (from 2.6.1) i'm getting this error:

ERROR in /home/PATH_TO_PROJECT/node_modules/io-ts-reporters/node_modules/io-ts/lib/index.d.ts
(213,31): error TS2344: Type '[P[K], Type<undefined>]' does not satisfy the constraint '[Type<any>]'.
  Types of property 'length' are incompatible.
    Type '2' is not assignable to type '1'.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.