type rec t = {
caseSensitive?: bool,
children?: array<t>,
element?: React.element,
index?: bool,
path?: string,
loader?: 'data. unit => promise<'data>,
action?: unknown, // TODO
errorElement?: React.element,
hydrateFallbackElement?: React.element,
@as("Component") component?: React.component<{}>,
@as("ErrorBoundary") errorBoundary?: React.component<{}>,
// handle?: unknown
shouldRevalidate?: bool,
@as("lazy") lazy_?: unit => promise<unknown>,
}
When actually attempting to use it gives this type error
60 │ caseSensitive: true,
61 │ element: <Settings />,
62 │ loader: async (type data, ()) => {
63 │ let response = await Fetch.fetch("/api/settings", {method: #GET})
. │ ...
66 │ json
67 │ },
68 │ }
69 │
This has type: unit => promise<Js.Json.t>
But it's expected to have type: 'data. unit => promise<'data>
Now I could reach for the GADT-style of binding the route objects, and in some respects that makes sense for the union type. But does anyone know how you could type-annotate this to use this feature? I can imagine a good number of Javascript APIs that’d become a lot less verbose to use with this–presuming you don’t have to use @send bindings to get polymorphic behavior on a record type with a function.
The target data seems dependent on the Settings component and not a generalized type.
And these original types are actually polymorphic at the implementation level. Making the polymorphism explicit or restricting it to be monomorphic in compile time wins in e2e quality, safety, and performance.
This will compile if the values are all left as JSON.t, but then it precludes having mixed response types in the APIs you call. There is also the option of typing all the RouteObject.loader properties to return a Response
I don’t much like either of these options, because I’d like to make the react-router hook useRouteLoaderData be able return a typed response for the route with the specific API response types. I feel I am pretty close to this using the GADT approach I tried after posting last night:
However the issue here is that @unboxed can’t be applied to just t_raw in the mutually recursive type definition, so it ends up being tagged in the compiled form, which wouldn’t work at runtime.
Yeah, I’d say you are right. The issue fundamentally is that it’s not a very rescript-y API I’m trying to bind to. I would rather trade off type safety in the route configuration, which isn’t actually used for much aside from creating the router instance via a binding, in order to get more type safety where consumers would actually use the data, via useRouteLoaderData, if at all possible.
Otherwise just make it polymorphic and create a a monomorphic abstract type with a identity function to go between the polymorphic and monomorphic types and use the monomorphic type where needed, like in arrays.