Search code examples
typescript

How to type check all elements in an array in TypeScript


How would I type check all elements in an array? CUrrently I am trying to do it with .every(), but the compiler is still unhappy. This return [animal, ...animals] does not work.

interface Dog {
    breed: string,
    age: number,
    alive: boolean
}

interface Cat {
    origin: string,
    height: number,
    furious: boolean
}

interface Fish {
    water: 'salty' | 'sweet'
    hemishphere: 'north' | 'south'
}

type Animal = Cat | Dog | Fish
type Animals = Cat[] | Dog[] | Fish[]


const isDog = (item: any): item is Dog => typeof item === 'object' &&
    item !== null &&
    "breed" in item &&
    "age" in item &&
    "alive" in item

const isCat = (item: any): item is Cat => typeof item === 'object' &&
    item !== null &&
    "origin" in item &&
    "height" in item &&
    "furious" in item

const isFish = (item: any): item is Fish => typeof item === 'object' &&
    item !== null &&
    "water" in item &&
    "hemishphere" in item


const animals: Animals = []

const setAnimals = (animal: Animal): Animals => {
    if(isDog(animal) && animals.every(a => isDog(a))) {
        return [animal, ...animals]    
    } else if(isCat(animal)) {
        return [animal]
    } else if (isFish(animal)) {
        return [animal]
    } else {
        return []
    }
    
}

Here is a PlayGround


Solution

  • Just put isDog to every() directly, seems a proper way to narrow animals to Dog[]:

    if(isDog(animal) && animals.every(isDog)) {