Created
September 22, 2021 02:02
-
-
Save odiak/725cd4a2745d4751541730b1681160f0 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import * as t from "io-ts"; | |
const codec = t.type({ | |
a: t.number, | |
b: t.union([t.string, t.undefined]), | |
}); | |
console.log(codec.decode({ a: 1 })); | |
type codec = t.TypeOf<typeof codec>; | |
// -------------------- | |
class Optional<A> extends t.Type<A | undefined> { | |
constructor(tp: t.Type<A>) { | |
super( | |
"Optional", | |
(u): u is A | undefined => u === undefined || tp.is(u), | |
(u, c) => (u === undefined ? t.success(undefined) : tp.validate(u, c)), | |
(a) => a | |
); | |
} | |
} | |
const optional = <A>(tp: t.Type<A>) => new Optional(tp); | |
type PresentPropKeys<P extends t.Props, K = keyof P> = K extends string | |
? P[K] extends Optional<infer _> | |
? never | |
: K | |
: never; | |
type OptionalPropKeys<P extends t.Props, K = keyof P> = Exclude< | |
K, | |
PresentPropKeys<P> | |
>; | |
type MyInterface<P extends t.Props> = t.IntersectionC< | |
[ | |
t.TypeC<Pick<P, PresentPropKeys<P>>>, | |
t.PartialC<Pick<P, OptionalPropKeys<P>>> | |
] | |
>; | |
const typeWithOptional = <P extends t.Props>(props: P): MyInterface<P> => { | |
const presentProps: t.Props = {}; | |
const optionalProps: t.Props = {}; | |
for (const [key, value] of Object.entries(props)) { | |
if (value instanceof Optional) { | |
optionalProps[key] = value; | |
} else { | |
presentProps[key] = value; | |
} | |
} | |
return t.intersection([ | |
t.type(presentProps as Pick<P, PresentPropKeys<P>>), | |
t.partial(optionalProps as Pick<P, OptionalPropKeys<P>>), | |
]); | |
}; | |
const codec2 = typeWithOptional({ | |
a: t.number, | |
b: optional(t.string), | |
}); | |
console.log(codec2.decode({ a: 1, b: undefined })); | |
type codec2 = t.TypeOf<typeof codec2>; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment