This was reported by @vasily-kirichenko in Gitter.
When you try to deserialize the F# Result type from JSON using ofJson, it doesn't seem to restore the type of the data, because comparing the data with an object of the same type fails with "data.Equals is not a function".
[<PassGenerics>]
let roundtrip x =
x
|> fun x -> JS.console.log (">", box x); x
|> toJson
|> ofJson
|> fun x' -> JS.console.log ("<", box x'); x'
type FancyInteger = { N : int }
let Test () =
let x = { N = 0 }
let wx : Result<_, unit> = Ok x
let wx' = roundtrip wx
match wx' with
| Ok x' ->
if x' = x then
()
else
failwithf "Unexpected data %A" x'
| res -> failwithf "Unexpected result %A" res
The given code fails at runtime with "matchValue.data.Equals is not a function". Before crashing, the code gives this output:
> Result { tag: 0, data: FancyInteger { N: 0 } }
< Result { tag: 0, data: { N: 0 } }
So it looks like the data loses its type information. Note that if I replace the Result type with a custom one (type MyResult<'a, 'b> = Ok of 'a | Error of 'b), the code gives the following output and passes:
> MyResult { tag: 0, data: FancyInteger { N: 0 } }
< MyResult { tag: 0, data: FancyInteger { N: 0 } }
dotnet fable --version): 1.3.5, build from masterYes, it's a very annoying bug, preventing passing Results to client.
I updated the code sample to use a record type. Too much "data" :smile:
The generated JS code for the Result type contains this:
[FSymbol.reflection]() {
return {
type: "Microsoft.FSharp.Core.FSharpResult",
interfaces: ["FSharpUnion", "System.IEquatable", "System.IComparable"],
cases: [["Ok", Any], ["Error", Any]],
};
}
If I change cases to the following, it works:
cases: [["Ok", GenericParam("T")], ["Error", GenericParam("TError")]],
Awesome, thanks a lot for the fix @inosik! You 馃暫
The fix has been published in version 1.3.5 :+1:
Most helpful comment
Awesome, thanks a lot for the fix @inosik! You 馃暫
The fix has been published in version 1.3.5 :+1: