Hi,
First, great library! Thanks for writing it, I'm having a lot of fun exploring it.
My biggest challenge so far is understanding the format of t.ValidationError. I'd like to build a reporter that returns a field errors dictionary object like: {[field: string]: string}.
With regular field I get one error with a context like ['', '', 'field'], but with unions, we get back 2 errors with a context like: ['', 'field', 0] and ['', 'field', 1].
I'm not sure how the context array is built. Would the first item ever be a non-empty string?
Is this a reliable way to retrieve the field name? i.e., by relying on the first non-empty key to be the field name?
function formatError (error: t.ValidationError) {
const field = error.context.find(c => c.key.length > 0)
return `Invalid ${field.key}`
}
BTW here is an example I'm playing with.
Working with it a bit more, here's another example with form validation in case anyone else finds it useful or has suggestions.
I'm not sure how the context array is built
function nullable<RT extends t.Any>(
type: RT,
name?: string
): t.UnionType<[RT, t.NullType], t.TypeOf<RT> | null, t.OutputOf<RT> | null, t.InputOf<RT> | null> {
return t.union<[RT, t.NullType]>([type, t.null], name)
}
const rxEmail = /^[^@\s]+@[^@\s]+\.[^@\s]+$/
const Email = t.refinement(t.string, s => rxEmail.test(s), 'Email')
const User = t.interface(
{
id: t.Integer,
username: t.string,
email: nullable(Email, 'NullableEmail')
},
'User'
)
const result = User.decode({
id: 123,
username: 'fred',
email: 'testtest.com' // '[email protected]'
})
if (result.isLeft()) {
console.log(
JSON.stringify(
result.value.map(validationError =>
validationError.context.map(contextEntry => `${contextEntry.key}: ${contextEntry.type.name}`)
),
null,
2
)
)
}
/*
[
[
": User", // <= root, its key is an empty string
"email: NullableEmail", // email field, key = "email"
"0: Email" // first type of the NullableEmail union, key = 0
],
[
": User", // root, the its is an empty string
"email: NullableEmail", // email field, key = "email"
"1: null" // second type of the NullableEmail union, key = 1
]
]
*/
TLDR
Context = Array<ContextEntry> is an array representing the path to the offending valueContextEntry usually refers to the root, hence its key is an empty string
Most helpful comment
TLDR
Context = Array<ContextEntry>is an array representing the path to the offending valueContextEntryusually refers to the root, hence itskeyis an empty string