In large codebases I try to write my code defensively to prevent against (accidental) misuse that might invalidate assumptions I made when writing it. I find that I occasionally want the concept of a “read-only” facet-like thing.
Somewhere else in the codebase I want to read the value of MySpecialNumber. But I don’t want anywhere else in the codebase to register MySpecialNumber.of(...). Its value should be defined internally in this module only.
Until now I’ve just been exporting a getter wrapper, like:
function getMySpecialNumber(state) {
return state.facet(MySpecialNumber)
}
But this kind of breaks down when I want to use MySpecialNumber in a dependency array for other computed things/ I don’t need to recompute every single time.
Wondering if there’s any other use cases for what I’m describing here. Thanks!
You may want to use the computed value here as a dependency somewhere, or maybe computing that value is quite expensive and so you only want it to be done once, so you create a facet for it. It would be nice if you could do something like:
I’m not sure what the actual API here would look like (the one above isn’t great), but this would cover the read only case (as you can only read the computed value, not provide a value to it). You could do this with a state field, but then consumers may still try to mount that field themselves or try to change the value of the field (e.g. with init).
TLDR: basically saying that you could probably cover the read only case and this derived/computed value case at the same time.
Regarding computed values, given that defining an extra facet for them already allows you to do that, I don’t think that really warrants another library feature.
As for facet handles that don’t allow you to set the facet, this patch adds something like that purely on the type level. Does that look like it would work for you?
Good point. It seems the lack of the Output type in the FacetReader interface’s properties made TypeScript fail to preserve the type parameter when casting from Facet to FacetReader (and I didn’t notice because, in the CM codebase, the @internal properties of the interface are still present, avoiding the issue). This patch should improve that.