Add `enum` support
Fixes https://github.com/gcanti/io-ts/issues/67 Fixes https://github.com/gcanti/io-ts/issues/216
The enum is a popular aspect of TypeScript, and can be embedded in
interfaces as a concise, but descriptive, shorthand for literal string
unions:
enum Colour {
White = '000000',
Black = 'ffffff'
}
This change adds an exported member enum to io-ts, based on
this suggestion by @noe132
It means that enums can be reused directly in io-ts:
const T = t.enum(Colour)
One place this does seem to fall down is that you lose the casting when extracting an interface. I can't quite figure out how to do that (possibly something to do with the encode function?). For example:
enum Colour {
White = '000000'
}
const Style = t.type({
colour: t.enum(Colour)
})
interface IStyle extends t.TypeOf<typeof Style> {}
const style: IStyle = {
colour: Colour.White
}
const colour = style.colour // colour has type "any" rather than "Colour"
I tried tweaking the signature for enumType:
const enumType = <E, A = E[keyof E]>(e: E, name: string = 'Enum'): EnumType<A> => {
const is = (u: unknown): u is A => Object.keys(e).some((k) => e[k as keyof E] === u)
return new EnumType<A>(name, is, (u, c) => (is(u) ? success(u) : failure(u, c)), identity)
}
...which seems to only succeed in disallowing a decode to string (which I guess is correct?), but still doesn't correctly cast.
This looks like it might work better, for string enums at least...
const enumType = <E>(
e: { [key: string]: E },
name: string = 'Enum',
): EnumType<E> => {
const is = (u: unknown): u is E => Object.keys(e).some(k => e[k] === u);
return new EnumType<E>(
name,
is,
(u, c) => (is(u) ? t.success(u) : t.failure(u, c)),
t.identity,
);
};
Re: [gcanti/io-ts] Add enum support (#366)
2020-02-16 2:56 غرينتش-08:00, jessmorecroft [email protected]:
This looks like it might work better, for string enums at least...
const enumType = <E>( e: { [key: string]: E }, name: string = 'Enum', ): EnumType<E> => { const is = (u: unknown): u is E => Object.keys(e).some(k => e[k] === u); return new EnumType<E>( name, is, (u, c) => (is(u) ? t.success(u) : t.failure(u, c)), t.identity, ); };-- You are receiving this because you are subscribed to this thread. Reply to this email directly or view it on GitHub: https://github.com/gcanti/io-ts/pull/366#issuecomment-586692616
Hey, since number enums have remapping, https://www.typescriptlang.org/docs/handbook/enums.html#reverse-mappings I think it's essential to check if the key is the remapped one.
enum E {
A = 1
}
// compiles to
const E {
A: 1,
'1': 'A',
}
In this case, 1 is valid, but 'A' is not.
https://www.typescriptlang.org/play?#code/KYOwrgtgBAolDeAoKUCCUC8UCMiC+QA
I've updated my code here https://github.com/gcanti/io-ts/issues/216#issuecomment-471497998
Any update on this?
+1 this would be a great addition, as currently I need to manually copy/paste my enum values into a t.union of t.literals
Okay I've updated this, and it now correctly casts!
Also updated to include @noe132 's update for checking for reverse mapping
Any update on this from @gcanti ?
Hi, what is the current status of this feature? We'd love to have enum support :)
@gcanti How do you feel about merging this in?
Is there anything stopping this feature from being merged?