-
Notifications
You must be signed in to change notification settings - Fork 40
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
Add case insensitivity for string type literals #134
Comments
@piersmacdonald we strive keeping io-ts mininal and lean. Io-ts-types repo is where such additional Types may be defined. |
Fair enough, thanks for the quick response. |
@piersmacdonald Did you come up with this type? I couldn't find it in io-ts-types. @gcanti is there easy way to achieve this with current Decoder? One way to do this is to have all literals in lowercase and then convert incoming string to lowercase and then forward it to D.literals decoder But this forces me to define all literal types in lowercase. const lowerCase = pipe(
D.string,
D.map((s) => s.toLowerCase())
)
const ComponentType = pipe(lowerCase, D.compose(D.literal('hcd', 'assembly')))
type ComponentType = D.TypeOf<typeof ComponentType>
console.log(ComponentType.decode('HCD')) |
@kpritam I would return the original input import * as E from 'fp-ts/lib/Either'
import { flow } from 'fp-ts/lib/function'
import * as D from 'io-ts/lib/Decoder'
const decoder: D.Decoder<unknown, string> = {
decode: flow(
D.string.decode,
E.chainFirst((s) => D.literal('hcd', 'assembly').decode(s.toLowerCase()))
)
}
console.log(decoder.decode('HCD'))
// => { _tag: 'Right', right: 'HCD' } |
@gcanti but this forces to define all the literals in lowercase, that might not what you always want. Basically is it possible to make decoding of following literals case insensitive? const compType = D.literal('Hcd', 'Assembly')
// all the following cases should pass and all should return **Hcd**
compType.decode('hcd')
compType.decode('Hcd')
compType.decode('HCD') |
Ah ok, I misinterpreted the requirements, I thought you always wanted the original input back |
import * as E from 'fp-ts/lib/Either'
import { flow, pipe } from 'fp-ts/lib/function'
import * as O from 'fp-ts/lib/Option'
import * as A from 'fp-ts/lib/ReadonlyArray'
import * as D from 'io-ts/lib/Decoder'
export const iliteral = <A extends readonly [string, ...Array<string>]>(
...values: A
): D.Decoder<unknown, A[number]> => {
const message = values.map((value) => JSON.stringify(value)).join(' | ')
return {
decode: flow(
D.string.decode,
E.chain((s) =>
pipe(
values,
A.findIndex((value) => value.toLowerCase() === s.toLowerCase()),
O.fold(
() => D.failure(s, message),
(i) => D.success(values[i])
)
)
)
)
}
} |
@gcanti great, thanks. Does it make sense for this to go into main library or io-ts-types? It is pretty common use case that these literal types are defined as case insensitive enums in other languages and then its upto codec library to decide how to encode/decode them. |
@kpritam ended up switching libraries for the job. This question was asked in the context of validating user requests for a REST service. So I switched to |
👍 once Decoder becomes official, moving to |
it's helpful to define an in put as being
t.keyof({ firstName: null, preferredName: null });
but it would be nice if they could sendfirstName
,firstname
, fIrStNaMe`The text was updated successfully, but these errors were encountered: