-
Notifications
You must be signed in to change notification settings - Fork 14
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
Should decoders match their decoded type exactly, or should there be multiple valid decoders for a type? #23
Comments
To tip my hand, I think it's reasonable to say that |
AB1, AB2, CD2, CD3, E1, E2. I'm aiming for a decoder that outputs values that are more specific or equal to the types defined. So, AB1 matches the type exactly. AB2 is more specific, in that a required number will always typecheck against an optional number. CD2 is more specific for a similar reason. A member of a branch will always typecheck against a union of itself. CD3 matches exactly. E1 matches exactly. E2 is the same as CD2. |
@RocketPuppy That might actually be the most balanced solution. It sounds like you think that
Strictly speaking both of those are valid |
Right, they aren't really distinct in Javascript, but they are distinct in subtle ways within Typescript. |
@RocketPuppy maybe I'm missing your point there, but they're distinct in JS -- e.g., the const ab = {a: true, b: undefined};
'b' in ab; // true
'c' in ab; // false |
I didn't know about the |
|
interface AB {
a: string;
b?: number;
} const decoderAB1 = object({
a: string(),
b: optional(number())
});
const decoderAB2 = object({
a: string(),
b: number()
});
const decoderAB3 = object({
a: string(),
b: union(number(), constant(undefined))
}); ... This one is tricky -- const decoderAB4 = object({
a: string()
}); I think, to keep consistent with TypeScript, type A = { a: boolean; };
const ab = { a: true, b: false };
const fa = (a: A) => a.a;
const t = fa(ab); // true |
interface CD {
c: string;
d: number | undefined;
} const decoderCD1 = object({
c: string(),
d: optional(number())
}); I think const decoderCD2 = object({
c: string(),
d: constant(undefined)
});
const decoderCD3 = object({
c: string(),
d: union(number(), constant(undefined))
});
const decoderCD4 = object({
c: string()
});
|
interface E {
e: string | number;
} const decoderE1 = object({
e: union(string(), number())
});
const decoderE2 = object({
e: string()
});
|
Sorry for the spam comments, esp. since I'm re-evaluating (I hadn't updated my mental model and was interpreting the |
Recently I've been exploring ways to require that the
optional
decoder be used for fields that are optional. From that process I've realized that I need to make a number of subtle design decisions related to how loosely or strictly a decoder needs to match a type. On the one hand, we should leverage typescript to help us write decoders that are as accurate as possible. On the other hand, I don't want the rules/guidelines around writing decoders to get too complicated, and I also don't want to be overbearing and prevent the user from writing the exact decoder they intend to.With all that in mind, I've got a few examples of situations where I could change the library to more strictly fit decoders to types. Please respond with feedback to the three questions, plus any other concerns or observations you've got.
AB
. All four decoders are valid and will compile without errors. In an ideal world, which of these decoders would you want to be valid, and which ones should produce an error?CD
. All four decoders are valid, but as a library user which ones would you want to be valid?E
.The text was updated successfully, but these errors were encountered: