Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Explicit Error Types (Decoder) #636

Closed
anthonyjoeseph opened this issue Mar 11, 2022 · 2 comments
Closed

Explicit Error Types (Decoder) #636

anthonyjoeseph opened this issue Mar 11, 2022 · 2 comments

Comments

@anthonyjoeseph
Copy link

anthonyjoeseph commented Mar 11, 2022

🚀 Feature request

zod, a runtime validation library, has an intuitive & statically typed dx that exposes possible errors at the type level

import { z } from "zod";

const User = z.object({ username: z.string(), password: z.string() });

const user = User.safeParse({ username: 123, password: 'secret' });

const usernameFailed: boolean = !user.success 
  && !!user.error.format().username
  //                          ^
  //             this is statically typed!

Current Behavior

const User = D.fromStruct({ username: D.string, password: D.string })

const user = decoder.decode({ username: 123, password: 'secret' })

const usernameFailed: boolean = pipe(
  user,
  E.fold(
    (e) => D.draw(e).includes('username'),
    () => false,            //     ^
  )                         //     |
  // have to look at the implementation of 'struct' to know this
) // could overlap with other errors

Desired Behavior

const user: E.Either<
  NonEmptyArray<{
    error: "Expected string";
    path: "username";
    received: Exclude<Primitive, 'string'>;
  } | {
    error: "Expected string";
    path: "password";
    received: Exclude<Primitive, 'string'>;
  }>, 
  string
>

Suggested Solution

A non empty array of a 'sum type' of errors

A bit clunky, but maximizes compile-time information

type DecodeError = { error: string }

type Decoder<I, E extends DecodeError, A> = {
  decode: (i: I) => Either<NonEmptyArray<E>, A>
}

declare const compose: 
  <A, E2 extends DecodeError, B>(to: Decoder<A, E2, B>) => 
    <I, E extends DecodeError>(from: Decoder<I, E, A>) => 
      Decoder<I, E | E2, B>

partial implementation (playground)

Who does this impact? Who is this for?

This approach is useful for displaying error messages (e.g. on forms), suggesting possible solutions, and/or recovering automatically from malformed input

Describe alternatives you've considered

A fork, or even a separate library (io-ts-validation?)

Additional context

Your environment

Software Version(s)
io-ts 2.2
fp-ts
TypeScript
@thewilkybarkid
Copy link
Contributor

Take a look at the proposed error change in #453 (comment).

@anthonyjoeseph
Copy link
Author

Woah! I had no idea. Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants