io-ts-types icon indicating copy to clipboard operation
io-ts-types copied to clipboard

Codec law does not hold for `optionFromNullable`

Open OliverJAsh opened this issue 3 years ago • 1 comments

🐛 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:

  • optionFromOptional: decodes undefined | T and encodes to undefined | T
  • optionFromNullable: decodes null | T and encodes to null | T

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

OliverJAsh avatar Dec 14 '21 09:12 OliverJAsh

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

huntwj avatar Jan 13 '23 03:01 huntwj