How to convince TypesSript you will return an Array with a property that is not null

I am working with the following types:

type Fruits = {
    type: 'banana' | 'peach' | 'kiwi',
    price: null | string; 
}


type FruitsWithNonNull = Pick<Fruits, 'type'> & {
    price: NonNullable<Fruits['price']>
} 

const fruits:Fruits[] = [{type:'banana', price:null}, {type:'peach',  price:null},{type:'peach', price:'12'}]

const filteredFruits:FruitsWithNonNull[] = fruits.filter(fruit => fruit.price !== null);

I get this error from filteredFruits:

Type 'Fruits[]' is not assignable to type 'FruitsWithNonNull[]'.
  Type 'Fruits' is not assignable to type 'FruitsWithNonNull'.
    Type 'Fruits' is not assignable to type '{ price: string; }'.
      Types of property 'price' are incompatible.

how can I convince typescript that when the filtering of the fruits is happening then the price is guaranteed to be there?

here is a link to the typescript playground

I am not that confident with typescript yet so not sure what the solution is here.

>Solution :

You can accomplish this with a user-defined type guard

type Fruits = {
    type: 'banana' | 'peach' | 'kiwi',
    price: null | string; 
}


type FruitsWithPrice = Pick<Fruits, 'type'> & {
    price: string;
}

const fruits: Fruits[] = [{type:'banana', price:null}, {type:'peach',  price:null},{type:'peach', price:'12'}];

const isFruitWithPrice = (x: any): x is FruitsWithPrice => {
    return x?.price !== null;
}

const filtered: FruitsWithPrice[] = fruits.filter(isFruitWithPrice)

Playground

Leave a Reply