typescript - Type-predikater fungerer ikke i 'utvidet' filterfunksjon


Jeg har to klasser:

class Dog {
  run() {
    console.log("RUN")
  }
}

class Fish {
  swim() {
    console.log("SWIM")
  }
}

Jeg lager deretter en type union gjennom:

type Pet = Dog | Fish

Jeg bruker deretter en type predicate for å evaluere hva som er superklassen til Pet-instanser:

function isDog(pet: Pet): pet is Dog {
  return (pet as Dog).run !== undefined
}

function isFish(pet: Pet): pet is Fish {
  return (pet as Fish).swim !== undefined
}

Jeg har deretter et array av Pet-er:

const zoo: Array<Pet> = [dog, dog, dog, fish, fish, fish]

Jeg vil gjerne filtrere arrayen slik at den kun har Fish-instanser, jeg gjør:

const underwater: Array<Fish> = zoo.filter(isFish)

som fungerer.

Hvorfor fungerer ikke dette i den 'utvidede' versjonen av filter funksjonen?

const underwater2: Array<Fish> = zoo.filter((p) => isFish(p))

Svar #1

Dette er den femte saken med åpen TypeScript-issue #38390. Selv om det kan være mulig å utlede type-predicate returtyper for enkle tilfeller, ser hovedproblemet ut til å være at det ville være en brytende endring.

Akkurat nå typekontrollerer denne koden:

const pets = zoo.filter(x => isFish(x));
// const pets: Pet[]

pets.push(new Dog()); // Allowed

Men hvis en typepredikat ville blitt utledet for pilfunksjonen, ville det feilet:

const pets = zoo.filter((p): p is Fish => isFish(p));
// const pets: Fish[]

pets.push(new Dog()); // Type error

Hvis nødvendig, kan du spesifisere typepredikatet i returtypen til pilfunksjonen (dvs. (p): p er Fish => isFish(p)):

const underwater2: Array<Fish> = zoo.filter((p): p is Fish => isFish(p))
// const underwater2: Fish[]

TypeScript-lekeplass