Home > Back-end >  Conditional in React Props
Conditional in React Props

Time:07-11

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);
    });
}
  • Related