I'm working on a component that takes in two props, inside
and position
. If inside
is set to true
, then position
can be left
or bottom
. If inside is set to false
, then position
can be left
, bottom
, right
or top
.
Here's what I have so far:
type InsidePosition = "bottom" | "left"
type OutsidePosition = "top" | "right" | InsidePosition
type CoordinatesProps =
| { inside: true, position: InsidePosition}
| { inside: false, position: OutsidePosition}
function Coordinates({ position, inside } : CoordinatesProps) {
const CoordinateComponent = inside ? InsideCoordinate : OutsideCoordinate;
return _.times(8, (index: number) => {
return <CoordinateComponent
key={ `${ position }-${ index }` }
index={ index }
position={ position }
/>;
});
}
The child components, InsideCoordinate
and OutsideCoordinate
, are defined like this:
type InsideCoordinateProps = {
position: InsidePosition,
index: number,
};
function InsideCoordinate({ position, index }: InsideCoordinateProps) {
...
}
type OutsideCoordinateProps = {
position: OutsidePosition,
index: number,
};
function OutsideCoordinate({ position, index }: OutsideCoordinateProps) {
...
}
The problem I'm running into is I'm getting a type error inside of Coordinates
at position={ position }
.
typescript: Type '"bottom" | "left" | "top" | "right"' is not assignable to type '"bottom" | "left"'.
Type '"top"' is not assignable to type '"bottom" | "left"'. [2322]
I could cast the position
value, but shouldn't the compiler be smart enough to know that position
can only be InsidePosition
when the component is InsideCoordinate
? Am I defining the function's type correctly?
CodePudding user response:
I had the exact same problem lately. Seems like TypeScript can't infer the type after restructuring so it doesn't work well with React.
I did something like that:
function Coordinates({ position, inside } : CoordinatesProps) {
const props = inside ? { position, inside } : { position, inside };
After this everything started to work fine.
CodePudding user response:
I don't think it can infer that unless you pass it immediately in the ternary check itself like so:
function Coordinates({ position, inside }: CoordinatesProps) {
const CoordinateComponent = inside
? (idx: number) => <InsideCoordinate position={position} index={idx} />
: (idx: number) => (
<OutsideCoordinate position={position} index={idx} />
);
return _.times(8, (index: number) => {
return CoordinateComponent(index);
});
}