You can define a reactive atom with a value that is readable and writable
You can define a derived value that is readable from a readable and writable atom
You CANNOT define a derived value from another readable derived value
In the original Jotai implementation, it is intended to support Readable → Readable derivatives. A quick test can be found at: jotai-demo (forked) - CodeSandbox.
I’m not very confident in my ReScript so upon looking around I have a suspect:
Specifically I’m thinking it’s the [> Permissions.r] part that seems to work as expected when you provide a default readable + writable as the source to get but not a readable.
Where I got stuck is I don’t recognize that syntax, despite my efforts I was unable to find a similar sample mentioned in the docs. I think it’s part of the destructuring\pattern-matching syntax but I’m not quite sure? Seems to act as some kind of guard?
I would like to know more about this so I can look into fixing it, even if the author is able to patch it before I can find a solution, it seems like a good learning opportunity. Is this something I just overlooked in the docs or some implied combination of the pre-existing concepts?
Ah thank you! I am not sure how I missed that, but I did
Now I understand it: It’s saying it as a minimum accepts Permissions.r but additional ones are fine because it’s open!
Turns out that it wasn’t the problem. It’s because of the following part:
let get = (type value, get: getter, atom: t<value, 'value => 'value, [> Permissions.r]>): value =>
Where the atom arg is defined as t<value, 'value => 'value, [> Permissions.r]> where that middle generic param is the setter which is not required for only readable atoms.
I was able to get tests to pass by changing it to the following: atom: t<value, _, [> Permissions.r]>
But I wonder if that has unforeseeable consequences being too relaxed there?
As of now I’m thinking the solution would be to create a variant type for the writer:
type void
type writer<'value> = void | ('value => 'value)
But I’m getting an error that it has no idea what | means there. Maybe it should be a smarter type where if it’s readable it doesn’t care about the writer param, otherwise it should be a function that takes a value and returns a value like the original?
I don’t think you want a variant type, because then you would have to do something along the lines of
type writer<'v> =
| Void
| Fn('v => 'v)
which defeats the purpose of what type void means. The key is that void has no constructor and thus is uninhabited. There’s no way to construct void in the program, so it can used as a placeholder for something that’s nonsensical.