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.
Link to the bindings: https://github.com/rescript-lang/rescript-react/blob/0f74265112bc8b725d361634fd49392a0ae29707/src/React.res#L56
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.
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.