javascript - TypeScript-fel med objektets egenskaper som möjligen är odefinierade trots att man kontrollerar för odefinierade värden med Object.values()


Jag har ett gränssnitt MentionItem med egenskaperna id och value, som båda måste vara strängar. Men TypeScript ger mig ett felmeddelande att dessa egenskaper möjligen kan vara string | undefined.

När jag manuellt kontrollerar att id och value inte är odefinierade, är TypeScript nöjd. Men när jag använder Object.values(dataset).includes(undefined) för att kontrollera odefinierade värden, klagar TypeScript fortfarande.

Varför ger TypeScript mig detta fel, och hur kan jag åtgärda det?

Här är min kod:
  interface MentionItem {
    id: string;
    value: string;
  }

  getItemData = (): MentionItem => {
    const dataset = (this.mentionList.childNodes[this.itemIndex] as HTMLElement).dataset;

    if(Object.values(dataset).includes(undefined)) {
      throw new Error("Incomplete dataset")
    }

    return {
      id: dataset.id,
      value: dataset.value,
    };
  };
Och här är TS-felet:
Type 'string | undefined' is not assignable to type 'string'. Type 'undefined' is not assignable to type 'string'.ts(2322)

Jag försöker förstå varför detta ger mig ett fel, eftersom det borde uppnå samma sak, rätta mig gärna om jag har fel:

Kontrollen som uppfyller TypeScript

if(dataset.id === undefined || dataset.value === undefined) {
  throw new Error("Incomplete dataset")
}

Kontrollen som stör TypeScript

if(Object.values(dataset).includes(undefined)) {
  throw new Error("Incomplete dataset")
}

Svar #1

Problemet ligger i den dubbla användningen av undefined i JavaScript.

  1. Om du försöker komma åt en objekt-egenskap som inte finns, returnerar JavaScript värdet undefined.
  2. Om du får åtkomst till en objektproperty som existerar men har satts till undefined, returnerar det också undefined.

Nu returnerar Object.values värdena för ett objekts egna egenskaper, inte undefined för egenskaper som inte finns. Därför

if(dataset.id === undefined || dataset.value === undefined) {
  throw new Error("Incomplete dataset")
}

fungerar för egenskaper som inte finns på dataset, eftersom åtkomst till dem returnerar undefined, villkoret uppfylls och felet kastas, men

if(Object.values(dataset).includes(undefined)) {
  throw new Error("Incomplete dataset")
}

misslyckas eftersom det inte finns några egna egenskaper hos dataset som uttryckligen har satts till undefined som kan hittas av includes-metoden, villkoret uppfylls inte, och felet kastas inte.