-
Notifications
You must be signed in to change notification settings - Fork 5
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
Optional type encodes to option<Js.Json.t> instead of Js.Json.t #85
Comments
I have a few questions.
@spice
type mystring = option<string>
let encoding = (str): Js.Json.t => {
str->mystring_encode
}
@spice
type mystring = option<string>
let encoding = (str): option<Js.Json.t> => {
str->mystring_encode
} |
Correct, the code was working prior to v0.2.2. I now understand that this change was introduced as part of the recent fix to support null and undefined. Since However, in this specific case, the correct solution would be for the encode function to always return At the moment, the function’s signature varies based on the input type. For an option, the signature is: type encoder<'a> = 'a => option<Js.Json.t> But for non-option types, the signature is: type encoder<'a> = 'a => Js.Json.t This inconsistency makes it difficult to use the encode function in a generic way. The function’s output type should remain consistent and always return (if we go this way) My use case: I’m building an encoder/decoder for my application’s network API. This ensures the protocol data is correct and raises a serialization error if it isn’t. This approach is much more robust than simply casting data to the expected type. However, for the encoder/decoder to work generically with all types (including I don’t know OCaml well enough to implement this change myself, but I believe the ideal fix would ensure that non-option types are also encoded as type encoder<'a> = 'a => option<Js.Json.t> To maintain symmetry, the decoder would be: type decoder<'a> = option<Js.Json.t> => result<'a> This change would break compatibility for some applications, but migration would be simple. It would also ensure consistency, unlike the current state, which only introduces breaking changes for option types. An alternative solution would be to revert the support for undefined and treat it the same as null. In my opinion, this approach could also work well for most use cases. |
It makes sense to me. How about the signatures of encoder/decoder functions: type encoder<'a> = 'a => result<Js.Json.t, Spice.encodeError>
type decoder<'a> = Js.Json.t => result<'a, Spice.decodeError> |
That would also be good, if I understand correctly. So this means that encoding This would actually be much simpler and better looking then changing Can you please clarify and elaborate, if this is what you meant, or something else? |
Exactly, yes. |
I agree this would be the best solution. |
Something came into my mind. This is important to keep options usable. So this, as we discussed above, resolves to encodeError: @spice
type t = option<string>
let str = None
switch t_encode(v) {
| Ok(v) => Js.log(t_encode(json)->Js.Json.stringify)
| Error(e) => Js.log("No json representation")
},
// => "No json representation" But, if option is in a record, what would it give? It should not give encodeError but it should convert to something, right? @spice
type t = {
foo: string,
value: option<string>
}
let v = { foo: "bar", value: None}
switch t_encode(v) {
| Ok(v) => Js.log(t_encode(json)->Js.Json.stringify)
| Error(e) => Js.log("No json representation")
},
// => {"foo": "bar"} Same with optional fields: @spice
type t = {
foo: string,
value?: string
}
let v = {foo: "bar"}
switch t_encode(v) {
| Ok(v) => Js.log(t_encode(json)->Js.Json.stringify)
| Error(e) => Js.log("No json representation")
},
// => {"foo": "bar"} I would assume that in both cases they end up to be valid json, with the optional field simply missing from the record? Am I correct with what these examples would log? Iow the record containing options would encode just as currently does. |
I see this on 0.2.2. This has changed recently, breaking my existing code.
This code gives an error:
So for some reason the payload type becomes
option<Js.Json.t>
if the item itself is optional. Shouldn't the encode result always be justJs.Json.t
?At the same time this works, so the problem is only with the first-level option.
I'll test this eventually with the newest code. (I am on 0.2.2 currently because Rescript v11 does not run with 0.2.3.)
The text was updated successfully, but these errors were encountered: