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

Issues when using intersection and types with fallback #532

Closed
mottetm opened this issue Nov 20, 2020 · 5 comments
Closed

Issues when using intersection and types with fallback #532

mottetm opened this issue Nov 20, 2020 · 5 comments
Assignees
Labels

Comments

@mottetm
Copy link

mottetm commented Nov 20, 2020

🐛 Bug report

Current Behavior

import * as t from 'io-ts';
import { withFallback} from 'io-ts-types';

const MyType = t.intersection([
  withFallback(t.type({ prop1: t.string }), { prop1: 'a' }),
  withFallback(t.type({ prop2: t.number }), { prop2: 1 }),
]);

MyType.decode(undefined); // throws: TypeError: Cannot read property 'prop1' of undefined

Expected behavior

As both of the subtypes will return a value when decoding undefined, the intersection should also succeed (or fail without exception).

MyType.decode(undefined) to be equal to right({ prop1: 'a', prop2: 1 })

Suggested solution(s)

The mergeAll function used to merge all types in the validation of the interface should be able to handle an undefined input. And skip the u[k] !== base[k] check.

@EricCrosson
Copy link
Contributor

@mottetm,

If you replace

MyType.decode(undefined)

with

MyType.decode({})

Then no error is thrown, as {} successfully decodes into {prop1: 'a', prop2: 1}.

I think this is working as intended, and the issue you're running into here is that the use of t.type means MyType is looking for an object to decode, which undefined does not satisfy.

Potential solutions:

You can use a fallback value in your call to decode:

MyType.decode(undefined ?? {})

Or you could implement this fallback as a part of your codec with withFallback.

@mottetm
Copy link
Author

mottetm commented Nov 20, 2020

@EricCrosson, I would agree with you if

withFallback(t.type({ prop1: t.string }), { prop1: 'a' }).decode(undefined);

failed. However, this is not the case as it successfully returns right({ prop1: 'a' }). As far as I understand it decoding an intersection should work if all codecs in it succeed. The issue is that currently the intersection does an assumption about the input type.

@samhh
Copy link

samhh commented Nov 20, 2020

I disagree that this is expected behaviour. The decode method types its foreign input as unknown, which suggests that you should be able to pass it anything. And, indeed, that's been my personal experience with the library. What's the point of a library that decodes foreign data if you have to refine it yourself first?

@gcanti gcanti added the bug label Nov 20, 2020
@gcanti gcanti self-assigned this Nov 20, 2020
gcanti added a commit that referenced this issue Nov 20, 2020
@gcanti gcanti closed this as completed in 2881d94 Nov 20, 2020
@gcanti
Copy link
Owner

gcanti commented Nov 20, 2020

@mottetm thank you for the bug report, patch released.

@mottetm
Copy link
Author

mottetm commented Nov 20, 2020

@gcanti Thanks for all the awesome work! 🙂

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

Successfully merging a pull request may close this issue.

4 participants