reactjs - props.items (Objekt) kan möjligen vara odefinierad efter tidigt returvillkor


Jag har sett några liknande frågor men ingen hade samma problem.

Jag blir förvirrad av objektet som eventuellt är odefinierat-fel från TypeScript.

interface Props {
  item?: SomeItem;
}

export const Element = (props: Props) => {
  if (props.item === undefined) {
    return null;
  }

  const offer = offers.find((offer) => offer.id === props.item.offer_id);

  return <div>{props.item.getPayoutPlaceholder()}</div>; 
};

Felet är

TS18048: 'props.item' kan vara 'undefined'. const offer=offers.find((offer) => offer.id === this.item.offer_id);

Det visas ENDAST på find-raden. Den sista (return) påverkas inte av detta.

Om jag tilldelar props.item till en konstant och använder den, slutar det

  const item = props.item;
  if (item === undefined) {
    return null;
  }

  const offer = offers.find((offer) => offer.id === item.offer_id);

Jag förstår att det kan ändras efter if av någon asynkron kod. Men det som verkligen förvirrar mig är det faktum att det inte visar samma fel i return-satsen. Vad kan vara orsaken till detta?

Svar #1

Detta beror på att props.item.offer_id är i en callback, och därför kan TS inte vara säker på att props.item inte har ändrats mellan tiden då du kontrollerar det och tiden då callbacken anropas. Som du noterade, kan du kringgå detta genom att definiera en konstant variabel:

const item = props.item;

Det bör också noteras att destrukturering också fungerar:

export const Element = ({ item }: Props) => {

men notera att ändring av const till let gör att det ursprungliga felet dyker upp igen:

let item = props.item;

och det är eftersom TS nu inte är säker på att det inte har förändrats, som tidigare (eftersom let är ändringsbart och kan tilldelas på nytt).

Användningen av props.item.offer_id fungerar i return-satsen eftersom den inte är i någon sorts kontext som kan ha fördröjd exekvering. Som ett exempel på detta, i följande kod, är TS tillräckligt smart för att se att detta funktionsuttryck kommer att anropas omedelbart och därför måste vara synkront:

// OK, even though it's in another function
(() => props.item.offer_id)();

Hur som helst, oavsett varför TS beter sig som det gör här, föreslår jag att du använder destrukturering direkt från parameterlistan. Det är rent, allmänt använt och löser detta problem direkt utan att behöva deklarera extra konstanta variabler.

Relaterade artiklar