Boxing / unboxing: unboxed list has length 0 (unboxing as an array works however)
Hi,
from the server, I return a boxed list
box [ DateTimeOffset.MinValue; DateTimeOffset.MaxValue ]
On the client, unboxing via
let datesAsList = unbox<DateTimeOffset list> datesFromServer
printfn $"datesAsList: length: {datesAsList.Length}, dates: {datesAsList}"
let datesAsArray = unbox<DateTimeOffset array> datesFromServer
printfn $"datesAsArray: length: {datesAsArray.Length}, dates: {datesAsArray}"
prints
datesAsList: length: 0, dates: 0001-01-01T00:00:00+00:00,9999-12-31T23:59:59.9999999+00:00
datesAsArray: length: 2, dates: 0001-01-01T00:00:00+00:00,9999-12-31T23:59:59.9999999+00:00
I would have expected: datesAsList has length 2, datesAsArray throws an exception.
Furthermore, trying to access
datesAsArray.[0].DateTime
throws
Uncaught TypeError: date.getTime is not a function
at fromDateTimeOffset (Date.js?a63a:161:1)
at eval (SearchTable.fs?840b:498:51)
at map (Array.js?34b9:77:1)
I found an ugly workaround with
unbox<string array> datesFromServer
|> Array.map DateTimeOffset.Parse
|> List.ofArray
@reneederer Why do you return a boxed list from the server?
On the client, I need to display a table with different column types. One of the columns has cells that contain list of dates.
I fetch the table rows from the server as list<list<obj>>, and in the date-column-case, obj is list<DateTimeOffset>
Is this understandable? Can I solve it without boxing/unboxing?
@reneederer I see, working with dynamic data can be annoying. Note that on the client side, unbox doesn't do anything at runtime! This is not a bug, that's by design. So depending on the shape of data (list<list<obj>> in this case) the runtime representation might not be unboxable to the type you want.
I do suggest you use a proper type for sending data from server to client:
[<RequireQualififedAccess>]
type TableField =
| Text of string
| Date of DateTimeOffset
| List of TableField list
type TableRow = TableRow of Map<string, TableField>
type DatabaseApi = {
events : unit -> Async<TableRow list>
}
Then on the client, you can try to render the data in the table or I am guessing you are using a component? Then you would have to write a utility function that converts the data into array<array<obj>> before giving that to the component
Ok, thanks for the quick answer!