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

t.record(NumberFromString, ...).is(value) always returns false #165

Open
mrdziuban opened this issue Dec 10, 2021 · 1 comment
Open

t.record(NumberFromString, ...).is(value) always returns false #165

mrdziuban opened this issue Dec 10, 2021 · 1 comment

Comments

@mrdziuban
Copy link

mrdziuban commented Dec 10, 2021

When using NumberFromString along with t.record, the is method of the resulting codec always returns false, e.g.:

t.record(NumberFromString, t.string).is({ 0: "test" })   // false
t.record(NumberFromString, t.string).is({ "0": "test" }) // false

Is there any way I could get this working without defining a custom codec? Thanks in advance!

P.S. I wasn't sure if I should open this issue here or in the base io-ts repository so let me know if you'd like me to re-open it there.

@EricCrosson
Copy link
Contributor

If we look at the code for NumberFromString1 we see the type-guard is implemented to check that the input value is a number. In general, for the AfromB codecs, the type guard checks for type A, which matches the decoded type A. In other words, type guards on these type-converting codecs are seemingly intended to be used on decoded values.

It seems like your first attempt in the snippet above would work, but Records are where things get tricky. First, note that t.record really only shines with the specific codec t.string in the domain (keys); even branded strings produce unacceptably-poor type inferencing (widens to any). This is probably why the domain is fixed as string (non-parameterized) in io-ts v3.

Technically in bare TypeScript Records accept a domain of string | number | Symbol but even this is a bit of a stretch of the truth -- in the node repl we can see

$ node                      
Welcome to Node.js v16.13.1.
Type ".help" for more information.
> const a = { 4: 'more' }
undefined
> a
{ '4': 'more' }
> a['4']
'more' 

that number keys are coerced into strings. This is probably why your first attempt failed, because the number you started with did not exist by the time your codec's type-guard ran.

If you need arbitrary types for your domain, consider using an es6 Map.

Footnotes

  1. https://github.com/gcanti/io-ts-types/blob/032c569f50a61befcee77412f1745b7bf9874885/src/NumberFromString.ts#L24

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