Typescript error when defining a state with OR operator
emroot opened this issue · 5 comments
Hey there,
I'm have this code:
import { hookstate, useHookstate } from '@hookstate/core';
interface DraggableStoreNotDraggingState {
dragging: false;
waiting: false;
}
interface DraggableStoreWaitingState {
dragging: false;
waiting: true;
waitingPoint: { x: number; y: number };
}
export interface DraggableStoreDraggingState {
dragging: true;
waiting: false;
startingPoint: { x: number; y: number };
currentPoint: { x: number; y: number };
}
type DraggableStoreState =
| DraggableStoreDraggingState
| DraggableStoreNotDraggingState
| DraggableStoreWaitingState;
export const InitalState = Object.freeze({
dragging: false as false,
waiting: false as false,
});
const DraggableStore = hookstate<DraggableStoreState>({ ...InitalState });
if (DraggableStore.waiting.get()) {
// typescript error
DraggableStore.waitingPoint.get();
}
Basically typescript says that waitingPoint
is undefined though waiting
is true.
How should this be done?
Thanks
The error is caused by the fact that the DraggableStore
state object is not guaranteed to have a waitingPoint
property when the waiting
property is true
. To fix this, you can add a type guard to check if the state object has a waitingPoint
property before trying to access it.
if (DraggableStore.waiting.get() && 'waitingPoint' in DraggableStore.get()) {
DraggableStore.waitingPoint.get();
}
Hope the advise above helped. If not please reopen.
I am having the same issue as above and the proposed solution is not working for me.
I have the following type
interface BaseHole {
surface: number,
x: number,
y: number,
}
interface CircleHole extends BaseHole {
shape: 'circle',
diameter: number,
}
interface SquareHole extends BaseHole {
shape: 'square',
width: number,
}
interface RectangleHole extends BaseHole {
shape: 'rectangle',
length: number,
width: number,
}
type Hole = CircleHole | SquareHole | RectangleHole
And the following React conditional
{
(hole.shape.value === 'square' && 'width' in hole.keys) &&
<NumberInput label="Width" value={hole.width.value} onChange={(e) => hole.width.set(e.target.value)} />
}
And I get the error
Property 'width' does not exist on type '__State<Hole, {}> & StateMethods<Hole, {}> & Omit<{ readonly shape: State<"circle", {}>; readonly diameter: State<number, {}>; readonly surface: State<...>; readonly x: State<...>; readonly y: State<...>; }, keyof StateMethods<...>>'.
I tried hole.keys and hole.get().
And on a related note I have the following select field
<select value={hole.shape.value} onChange={(e) => hole.shape.set(e.target.value as 'circle' | 'square' | 'rectangle')}>
<option value="circle">Circle</option>
<option value="square">Square</option>
<option value="rectangle">Rectangle</option>
</select>
And I get the following error
Argument of type '"circle" | "square" | "rectangle"' is not assignable to parameter of type '(SetStateAction<"circle"> & SetStateAction<"square">) & SetStateAction<"rectangle">'.
Type '"circle"' is not assignable to type '(SetStateAction<"circle"> & SetStateAction<"square">) & SetStateAction<"rectangle">'