A few small questions

They’re the same, however, use the latter one.

How can I “nest” types?

Right now, I am working with MongoDB. This is how I’m thinking about structuring the type:

I have Document.t<'a> which is what is returned from the DB on query (option<Document.t…>). A document, however could be of different types depending on the collection I’m querying. For example, it might be Document.t<User.t>.

I need to be able to call some sort of save() method using the Document.t type, but I also need to be able to access the fields of User.t.

What would be a sane way to structure the type, or what would be a sane way to work with the object?

Would need to see an example of using it in plain JS to figure out how to target the usage in ReScript.

Ok, pseudocode:

function mongoDbFind<T>(query: any): Document<T> | null ...

function findUser(email:string): Document<User> | null ...

const user = findUser("user@somedomain.com")

const id = user.id // from Document<T>
const email = user.email // from User

In essence, Document is a wrapper around User. A User is guaranteed to have the field email, and a Document is guaranteed to have the field id

How can I compose a type in ReScript so I can access both id and email on the object?

What I’m doing right now:

module Document = {
  type t<'a> = 'a
}

I think this would be sort of what I’m trying to do:

module Document = {
  type t<'a> = {
    id: string,
    ...'a
  }
}

Maybe I’m missing the complexity here but this looks pretty simple to me:

type user = {
  id: string // note, I'm assuming this is a string, you will know better
  email: string,
}

@val
external findUser: string => user = "findUser"

I think the complexity is separation-of-concerns. I’m composing multiple different types of documents, but they are all mongo documents.

This means that id should be in document, but email should be in user (just as an example).

How should I think about {…} - is it type safe, and how can I convert a JSON object to a {…} (assuming it isn’t type-safe!?}

How can I deal with polymorphic interop?

E.g., React sends an array of React.element or a React.element depending on whether someone is using my component with one or many children. I need to ensure it is always an array. Can I do this with ReScript or should I used %raw?

You can think of it as equivalent to TypeScript’s object type, it allows treating the value as an object and getting any field from it. There’s no guarantee that the object actually has those fields though, so it’s not particularly typesafe. You can convert a JSON object to various types but the goal should usually be to convert it into a record type which offers maximum safety and convenience.

React sends an array of React.element or a React.element depending on whether someone is using my component with one or many children. I need to ensure it is always an array.

Can you show some example code of how this is done in JavaScript?

Thank you.

JS solution: children = Array.isArray(children) ? children : [children]

I think the complexity is separation-of-concerns. I’m composing multiple different types of documents, but they are all mongo documents.

Gotta ask yourself, is the complexity from separaing these concerns actually gaining you any value in the long run? Are there often times where you want a user that doesn’t have an ID?

A way around it is to treat Document.t as a box with an ID that contains a value, and then use an identy casting function to “extract” the data

module Document = {
   type t<'a> = {id: string}
   external data: t<'a> => 'a = "%identity"
}

let userDocument: Document.t<user> = {/**/}

let id = userDocument.id
let user = Document.data(userDocument)

children = Array.isArray(children) ? children : [children]

hmm I can’t think of a use case where modifying the react children would be useful except for intentionally calling Array.map on them to do something, which that I would consider an anti pattern. You can probably implement something similar using context

No, the complexity definitely isn’t worth it, I’m just trying to learn how to do things properly in ReScript. Thank you so much for your reply, that was a really neat way of doing it.

hmm I can’t think of a use case where modifying the react children would be useful except for intentionally calling Array.map on them to do something, which that I would consider an anti pattern. You can probably implement something similar using context

So, the thing is, if your React component receives a single child, children is not an array. If you receive multiple children, children is an array.

Therefore, if you’re looking to do some form of map operation on the children, you first have to make sure it’s an array. That’s where my snippet comes into play.

There’s React.Children, module with map, forEach and other stuff.

1 Like

Link to the bindings: https://github.com/rescript-lang/rescript-react/blob/0f74265112bc8b725d361634fd49392a0ae29707/src/React.res#L56

How would I do if (a instanceof Error) ... in ReScript?

You can do it only with %raw

Why would you need to do a instanceof Error? Perhaps there is a more idiomatic way of doing what you are trying to accomplish.

1 Like

To add to this, note that this isn’t just a ReScript thing. In ReactJS you should treat children as opaque and use the React.Children functions.

3 Likes