gcanti / io-ts-types

A collection of codecs and combinators for use with io-ts
https://gcanti.github.io/io-ts-types/
MIT License
311 stars 40 forks source link

Codec law does not hold for `optionFromNullable` #166

Open OliverJAsh opened 2 years ago

OliverJAsh commented 2 years ago

🐛 Bug report

Current Behavior

The following law as defined here:

pipe(codec.decode(u), E.fold(() => u, codec.encode)) = u for all u in unknown

import * as assert from "assert";
import * as E from "fp-ts/Either";
import { pipe } from "fp-ts/function";
import * as t from "io-ts";
import { optionFromNullable } from "io-ts-types";

const codec = optionFromNullable(t.string);

const u = undefined;

// ❌ This fails because the encode result is `null`, not `undefined`
assert.strictEqual(
    pipe(
        codec.decode(u),
        E.fold(() => u, codec.encode)
    ),
    u
);
AssertionError [ERR_ASSERTION]: Expected values to be strictly equal:
+ actual - expected

+ null
- undefined

Expected behavior

Reproducible example

See above.

Suggested solution(s)

Currently we have optionFromNullable which decodes undefined | null | T and encodes to null | T.

Perhaps we could separate this into two codecs:

Additional context

Your environment

Which versions of io-ts-types are affected by this issue? Did this work in previous versions of io-ts-types?

Software Version(s)
fp-ts
io-ts
io-ts-types
TypeScript
huntwj commented 1 year ago

I see this is a year old, but I would also like to see this happen.