Consider the following logic:
There is a multi step form with exactly four steps and a back button. A user can go forward and backwards, but if he is on the first or last step, the back button should go to the previous screen.
Now consider the code made to satisfy that (It was made with React Native, but it can be done similarly independent of the context):
const [step, setStep] = useState<1 | 2 | 3 | 4>(1)
// ...
if (step === 1 || step === 4) {
// exit the screen
} else {
setStep(step - 1)
}
The line inside the else
block shows Argument of type 'number' is not assignable to parameter of type 'SetStateAction<2 | 1 | 3 | 4>'. ts(2345)
. However, hovering step
inside the else
block gives the type 2 | 3
, which should be fine to subtract 1, since the minimum value possible is 1.
Is this a bug? Am I missing something? How can I write valid code for this use case?
2
Answers
Whilst you might be providing a number you’re registering a concrete type against
step
. It’s no different to doing:Due to this you can’t reduce the value by N as typescript doesn’t see it as a numeric format.
The only way off the top of my head you’d be able to resolve this is with:
Types don’t do math.
step - 1
is typenumber
which is broader than1 | 2 | 3 | 4
.One path would be to remove the subtraction:
but that becomes quite easily error prone and is less obvious. In this case I guess I would "help" the compiler by casting
It’s also worth creating a type alias to avoid duplicating the type (e.g.
type Steps = 1 | 2 | 3 | 4
).