Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Typescript filter showing error is not assignable to type

Tags:

typescript

This is not working. Shows error Type '(Person | null)[]' is not assignable to type 'Person[]'. Type 'Person | null' is not assignable to type 'Person'. Type 'null' is not assignable to type 'Person'.

interface Person {
  name: string;
}

function filterPersons(persons: Array<Person | null>): Array<Person> {
    return persons.filter(person => person !== null)
}

function run() {
    const persons: Array<Person | null> = []
    persons.push(null)
    filterPersons(persons)
}

run()

But this is working

interface Person {
  name: string;
}

function filterPersons(persons: Array<Person | null>): Array<Person> {
    return persons.filter(person => person !== null) as Array<Person>
}

function run() {
    const persons: Array<Person | null> = []
    persons.push(null)
    filterPersons(persons)
}

run()

Any explanation & are there any better solution? Thanks 🙂️

like image 806
ARIF MAHMUD RANA Avatar asked Jan 25 '23 16:01

ARIF MAHMUD RANA


2 Answers

The first piece of code persons.filter(person => person !== null) does not typecheck because TSC is unable to understand that your code is actually narrowing array item type to be Person.

You can help it by declaring your filter function as a type guard. Playground.

interface Person {
  name: string;
}

// notice person is Person return type
const isPerson = (person: Person | null) : person is Person => person !== null

function filterPersons(persons: Array<Person | null>): Array<Person> {
    return persons.filter(isPerson)
}

function run() {
    const maybePersons: Array<Person | null> = []
    maybePersons.push(null)
    const persons: Person[] = filterPersons(maybePersons)
    console.log(persons)
}

run()
like image 183
Yury Tarabanko Avatar answered Jan 27 '23 04:01

Yury Tarabanko


filter currently cannot apply type guards, there is an open issue for this.

like image 21
H.B. Avatar answered Jan 27 '23 06:01

H.B.