Skip to content

Instantly share code, notes, and snippets.

@spacejack
Created January 14, 2020 01:08
Show Gist options
  • Save spacejack/80fffc69af242ae76c04fdd3fd7c55da to your computer and use it in GitHub Desktop.
Save spacejack/80fffc69af242ae76c04fdd3fd7c55da to your computer and use it in GitHub Desktop.
import * as t from './io-ts'
type FieldErrors<T = Record<string, any>> = Partial<Record<keyof T, string>>
/** Creates an empty FieldErrors object for the specified entity type. */
function FieldErrors<T = Record<string, any>>() {
return {} as FieldErrors<T>
}
// Helpers
namespace FieldErrors {
/**
* Creates a FieldErrors object from an io-ts ValidationError array.
* Provide the record type that the field error keys should match.
* @param errors The array of errors
* @param formatter An optional callback that returns an error message.
*/
export function from<T = Record<string, any>>(
errors: t.ValidationError[],
formatter?: (field: keyof T, value: any) => string
): FieldErrors<T> {
return errors.map(
e => [validationErrorKey<T>(e), e.value] as [keyof T, any]
).reduce((fieldErrors, [key, value]) => {
// Only count non-empty, non-numeric keys
if (key && !Number.isSafeInteger(Number(key))) {
if (!fieldErrors[key]) {
fieldErrors[key] = formatter
? formatter(key, value)
: `Invalid ${key}.`
}
}
return fieldErrors
}, FieldErrors<T>())
}
}
/** Helper function returns the field name from the ValidationError */
function validationErrorKey<T> (error: t.ValidationError) {
let key = ''
// Use the entry with longest key to get the field name
for (const c of error.context) {
if (c.key.length > key.length) {
key = c.key
}
}
return key
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment