type narrowing signals
I've got some state (I'm making a card game) that looks like
and then my signal to track game state ends up looking like
over time, i want to update this object. since i'm using discriminated types, if i want to reason about any of the props that only exist on
GamePaused
or GameOver
, I need to do some narrowing.
it seems like doing a if (gameState().state !== "playing") { return } ... gameState().___
doesn't successfully autocomplete. I'm assuming that typescript doesn't have enough info to guarantee that the 2nd getter invocation will be equivalent to that of the first.
Next reasonable idea is to invoke the getter once and store in a variable, then use that to type narrow. But then when I do a setGameState(...) using that variable, I'm not following the nested reactivity pattern here https://www.solidjs.com/tutorial/stores_nested_reactivity
Any thoughts/best practices here ?10 Replies
Could you give an example of what you mean by "nested reactivity pattern"? The way you are doing it by assigning to a variable to help narrowing typescript is completely fine.
The tutorial is an introduction to stores which essentially create signals for each property access internally so that you won't have to do so manually for each nested property you want to be reactive
I just noticed that the example called the signal directly inside the side, as opposed to creating a variable, that's what I was referring to
But if it doesn't matter, then ok that's cool. I'm running into some ugly typescript issues then it looks like
What about when I have something like
Is there anyway to narrow such that if we know state is
Accessor<"playing">
, then we will know that setState is Setter<"playing">
?
I'm trying some hacky things to get it going, but am getting that my setState is not callable This expression is not callable.Each member of the union type 'Setter<"playing"> | Setter<"paused"> | Setter<"over">' has signatures, but none of those signatures are compatible with each other.
I think it's not narrowing successfully is the issuee but can't find a solution. doesn't do anything for me reallyI think for your
Game
type definition it doesn't need state
. Just a union of GameInProgress | GamePaused | GameOver
should be enough to define GameSorry, 1 sec, I've overhauled the types a fair bit
this is what i changed it to
Also in this case maybe separating gameState into it's own variable first will work better
yea i've tried that. it doesn't affect the setter at all though
hmm not too sure, is there a reason for those values to be accessor and setters?
They are only storing one value based on the types
I'd recommend just assigning the result of
gameState
to a separate value and using that. Doing fancy types and stuff with the setter and adding more accessors won't help since you still need to discriminate between the different accessors.
I had something much like this originally, any time p1Flipped or p2Flipped are updated, the ui that depends on either of them are both updated. That's why I moved to using signals inside the state object
In that case wouldn't a store be better?