javascript - filter i typescript fick felmeddelandet '(string | null)[]' kan inte tilldelas


Jag har en array av objekt, en av egenskaperna har ett null-värde, jag använde filter för att ta bort det, men TypeScript ger mig en varning att null inte kan tilldelas? Eftersom filter aldrig kommer att returnera null, varför ger TypeScript mig ett sådant fel?

const data = [
  {
    id: "123"
  },
  {
    id: "456"
  },
  {
    id: null
  }
];

const d2: string[] = data.map((d) => d.id).filter((o) => o);

console.log(d2);

demo https://codesandbox.io/s/gallant-water-vio56?file=/src/index.ts:0-165

Svar #1

UPPDATERING SEPTEMBER 2024:

Från och med TypeScript 5.5 kan TypeScript nu härleda typpredikat.

Men koden i frågan skulle fortfarande inte fungera, och anledningen till detta är att funktionen kan returnera en tom sträng. Denna möjlighet till en tom sträng innebär att det fortfarande finns en möjlighet att du gjorde ett misstag, och därför behåller TypeScript felet för att tvinga dig att ta en titt.

Du kan antingen lägga till en explicit returtyp (Se det ursprungliga svaret nedan), eller så kan du ändra koden så att den tomma strängen inte längre filtreras bort:

const d2: string[] = data.map((d) => d.id).filter((o) => o !== null);

Lekplatslänk


ORIGINELLT SVAR:

Typescript kan inte lista ut att .filter((o) => o) kommer att begränsa typerna av arrayen, inte utan viss hjälp. Du kan dock definiera en egen typvakt och använda den. Till exempel:

function notNull<T>(val: T | null): val is T {
    return val !== null;
}

const d2 = data.map((d) => d.id).filter(notNull); // d2 is a string[]

Eller en inline-version som bara fungerar med strängar:

const d2 = data.map(d => d.id).filter((o): o is string => !!o);

Lekplatslänk

Svar #2

Att använda filter kommer inte att begränsa typer åt dig. map omvandlar datan till en array av string | null-data, och TypeScript vet inte att d2 inte kommer att innehålla null efter filtrering (TypeScript är nog inte särskilt smart, antar jag...).

Det finns ett par lösningar — en av dem är komplicerad, och den andra är komplicerad (även om inte så komplicerad) jämfört med din ursprungliga kod.

Använd typkontroll

Vi kan uttryckligen använda typer i filterfunktionen själv så att TypeScript vet att resultatet inte kommer att innehålla null:

const data = [
  { id: "123" },
  { id: "456" },
  { id: null }
];

// Type guard to filter out null values
const d2: string[] = data.map((d) => d.id).filter((o): o is string => o !== null);

console.log(d2);

Länk till kod

Kasta resultatet efter filtrering

Vi kan också bara typomvandla resultatet efter att filtret har körts istället för att tilldela typen i förväg. Lägg bara till as string[] i slutet av din rad:

const data = [
  {
    id: "123"
  },
  {
    id: "456"
  },
  {
    id: null
  }
];

const d2 = data.map((d) => d.id).filter((o) => o) as string[];

console.log(d2);

Observera: Det är en bra praxis att också inkludera !== null, så här:

const d2 = data.map((d) => d.id).filter((o) => o !== null) as string[];

Men det är inte nödvändigt, och jag försökte eftersträva enkelhet i den andra lösningen…

Länk till kod

Relaterade artiklar