Thank you, this clarified it for me.
The cors API returns an Error if something fails, otherwise some success object:
type corsFn = (Next.Request.t, Next.Response.t, t => unit) => unit
@module("cors")
external create: {..} => corsFn = "default"
let allow = (corsFn: t, req: Next.Request.t, res: Next.Response.t) =>
Promise.make((resolve, _) =>
corsFn(req, res, result => {
//if (result instanceof Error) {
//reject(result)
//return
//}
resolve(. result)
})
)
Which cors API is this? Can you point to some documentation or post a JavaScript example which shows the behaviour?
Thank you @yawaramin. I appreciate your effort to help but we’re focusing too much on the specifics. Imagine that such an API exists - how do I tackle it with ReScript? After all, it’s ReScript that I need help wrapping my head around, not some bad API specification!
Just asking because I’ve never come across any API that actually returns an Error
object on failure (instead of throwing an exception or returning null
or calling an onError
handler).
Actually it’s a good pattern in typescript, because this way you can describe possible errors of an API with typesystem. It’s kind of an alternative of result type.
But don’t forget difference between error and exception flow, when use something like this.
For this case, I’d either create a function to test instnanceof Error, or a function to convert it to ReScript’s result type. But you need to use %raw for the instanceof anyway.
So basically (in TypeScript terms) type Result<A> = A | Error
? OK, I get it. Imho not a great approach (what happens when A
is supposed to be Error
) but can of course be handled with %raw
.
No, in this approach you directly type data or a function return value without creating result type. In this case the code using this approach looks very similar to go, where after every function call you have an if statements, handling possible errors.
To be able to map over result in typescript people usually use a third-party library with either-monad. I personally used sweet-monads/either at master · JSMonk/sweet-monads · GitHub
I’ve never seen such a problem using this approach.
Is --save-dev correct for rescript?
I’m using npm ci --omit=dev when building my docker image and it can’t run because the rescript module doesn’t exist. I think this is an error in the documentation!?
Usually it’s correct to save in dependencies
as it has modules which need to be used at runtime. The docs should probably be fixed here.
Thanks.
How do I merge two dictionaries in ReScript?
I’m used to doing {…a,…b} but ReScript is only allowing one spread operator it seems.
If you are talking about Js.Dict.t
, you would need to write your own binding to Object.assign
.
let dictA = [("1", 1), ("2", 2), ("3", 3)]->Js.Dict.fromArray
let dictB = [("4", 4), ("5", 5), ("6", 6)]->Js.Dict.fromArray
@val
external assign: (Js.Dict.t<'a>, Js.Dict.t<'a>) => Js.Dict.t<'a> =
"Object.assign"
let dict = assign(dictA, dictB)
However, you mostly only need Js.Dict.t
for interop with JS libraries.
Prefer using Maps where possible. Belt.Map.String
for instance has a merge
and a mergeMany
method.
Right now, I have (typeless) objects stored in a database. I’m converting them to Js.Dict when loading. Is that a bad idea? How would I convert them to Map?
E.g.
let myMap = myDict->Js.Dict.entries->Belt.Map.String.fromArray
I don’t know if it is a bad idea, but it for sure adds some runtime. What do you mean by convert? Is it just an external or does it produce extra JS code?
It’s better to convert these objects into strongly-typed record objects with a schema i.e. the ‘parse, don’t validate’ philosophy.
How can I use ReScript React components from a JSX project? I cannot get it to work and I’m getting all sorts of esoteric errors that I don’t understand.
Nevermind that, I got it to work. However, I cannot do nested components. For example, I like to have Page and Page.Section, but it seems I cannot do that and get it to work in regular JSX
Unless I missed some prior questions, the following should get you a Page
and Page.Section
components. Of course the outer module Page
could also be a Page.res
file instead
module Page = {
@react.component
let make = (~children) => <div className={"section"}>{children}</div>
module Section = {
@react.component
let make = (~children) => <div className={"section")>{children}</div>
}
}
// Usage
<Page><Page.Section>{React.string("Hello")}</Page.Section><Page.Section>{React.string("Subcomponent")}</Page.Section></Page>
Thank you.
Yes, but I want to use them from “normal JSX” files. I really don’t, but I have to because Next.js maps file names to routes and under each dir, I need an index.res file and that doesn’t work with ReScript because the filename has to be unique per project, so therefor I’m going to use .jsx files for the pages and ReScript for everything else.