filtering an array with typescript
|

How to filter an array of objects in Typescript, the easy way

Filtering is something that you would often do in your Javascript and Typescript applications. We’ll be using Array.filter() to achieve this and to make the information more digestible, we will start with a simple array.

Filtering an Array of Numbers

so let us say we have an array of numbers

const data = [0, 1, 3, 4, 5, 6, 7, 8, 9];

and we want to filter it to just the numbers that are above 5. To do so, we can utilize Array.filter() this way:

const data = [0, 1, 3, 4, 5, 6, 7, 8, 9];

const filtered = data.filter((value) => value > 5);

console.log(filtered);
output

Inside the filter function, we used something called a Predicate Function, and it was this one here:

const filtered = data.filter((value) => value > 5);
                             // 👆

The Predicate function

Alright, that was wonderful, but let us have a deeper dive into understanding what Predicate Function is. In definition: It’s a function that runs on each item of the array and returns either a true or a false value, also known as a boolean.

But what does that mean in practice?

in our previous example, we had an array of numbers. When we use the filter function, what happens behind the scenes is that it iterates (loops) over every value, and runs the function that we provided while passing the iterated value.

so based on our example, this would mean:

(0) => 0 > 5 // false
(1) => 1 > 5 // false
(2) => 2 > 5 // false
(3) => 3 > 5 // false
(4) => 4 > 5 // false
(5) => 5 > 5 // false
(6) => 6 > 5 // true
// and so on..

Each time the Predicate Function returns a true value, Array.filter() will return the value we tested to the new array that we defined in filtered.

A common mistake when using Array.filter() is this:

const filtered = data.filter((value) => {value > 5}); //❌

developers would think the issue is the logic of their filtering, while in reality, the issue is syntax.

output

While it’s handy that eslint is pointing out where the issue is, it’s good to understand the syntax to avoid it.

data.filter((value) => value > 2) // ✅ this syntax
data.filter((value) => {return value > 2}) // ✅ is a short hand of this

this is because the Predicate Function must return a boolean, remember?

and data.filter(()=>{value > 2}) returns nothing.

Filtering an Array of Objects

Now that we understand how Array.filter() and the Predicate function work, we can dive into more complex examples.

We will start by defining our data:

type CatBreed = "persian" | "bengal" | "sphynx" | "british shorthair";

interface Cat {
  name: string;
  breed: CatBreed;
  ageInYears: number;
}

const catsData: Cat[] = [
  { name: "Bella", breed: "british shorthair", ageInYears: 1 },
  { name: "Milo", breed: "persian", ageInYears: 5 },
  { name: "Sadie", breed: "british shorthair", ageInYears: 3 },
  { name: "Ziggy", breed: "persian", ageInYears: 6 },
  { name: "Salem", breed: "sphynx", ageInYears: 11 },
  { name: "Cleo", breed: "bengal", ageInYears: 7 },
  { name: "Daisy", breed: "sphynx", ageInYears: 3 },
  { name: "Pepper", breed: "persian", ageInYears: 9 }
];

now let us say that we want to create a filter to output all the Persian cats that we have.

type CatBreed = "persian" | "bengal" | "sphynx" | "british shorthair";

interface Cat {
  name: string;
  breed: CatBreed;
  ageInYears: number;
}

const catsData: Cat[] = [
  { name: "Bella", breed: "british shorthair", ageInYears: 1 },
  { name: "Milo", breed: "persian", ageInYears: 5 },
  { name: "Sadie", breed: "british shorthair", ageInYears: 3 },
  { name: "Ziggy", breed: "persian", ageInYears: 6 },
  { name: "Salem", breed: "sphynx", ageInYears: 11 },
  { name: "Cleo", breed: "bengal", ageInYears: 7 },
  { name: "Daisy", breed: "sphynx", ageInYears: 3 },
  { name: "Pepper", breed: "persian", ageInYears: 9 }
];

const filteredData = catsData.filter((cat) => cat.breed === "persian");

console.log(filteredData);
output

As we understood earlier, the Predicate Function is iterating over each value of the array. This time, the values of our arrays are objects of type Cat rather than a Number.

Objects have properties that can be accessed with the dot . sign.

cat.name
cat.breed
cat.ageInYears

Once again, iterating through our array with the filter would mean:

// 👇 { name: "Bella", breed: "british shorthair", ageInYears: 1 }
(cat) => cat.breed === "persian"  /// false
            //👆 "british shorthair"

// 👇 { name: "Milo", breed: "persian", ageInYears: 5 }
(cat) => cat.breed === "persian"  /// true
            //👆 "persian"

// and so on..

Filtering an Array of Objects based on multiple properties

We can filter based on multiple properties rather than just one. We can also combine them with:

and

Where all conditions must be true.

Example: We want to filter to cats that are a Persian breed and older than 5 years.

const filteredData = catsData.filter(
  (cat) => cat.breed === "persain" && cat.ageInYears > 5
);
output

or

Where either condition has to be true.

Example: We want to filter to cats that are either Persian or British Shorthair

const filteredData = catsData.filter(
  (cat) => cat.breed === "persian" || cat.breed === "british shorthair"
);
output

both

where you can mix and match

Example: We want to filter to cats that are either Persian or British Shorthair, and they are older than 2 years.

const filteredData = catsData.filter(
  (cat) =>
    (cat.breed === "persian" || cat.breed === "british shorthair") &&
    cat.ageInYears > 2
);
output

Filtering an Array of Objects based on conditions

Taking things a step further, we can really expand our filtering logic as much as we would like, as long as our function is returning a boolean in the end.

Example:

If a cat is a sphynx breed, then get the ones that are younger than 5 years.

If a cat is Persian breed, then get the ones that are older than 5 years.

const filteredData = catsData.filter((cat) => {
  if (cat.breed === "sphynx") {
    return cat.ageInYears < 5;
  }
  if (cat.breed === "persian") {
    return cat.ageInYears > 5;
  }
  return false; // This means that anything that didn't apply with our previous logic will not be returned to filteredData
});
output

Notice how we used a different syntax this time.

catsData.filter((cat) => {/*filtering logic*/})

this is because we needed to use if conditions, which wouldn’t work with the shorthand syntax.

Conclusion

Array.filter() is one of the most powerful features in Javascript/Typescript. Understanding how it works, and how you could manipulate it further will really help you out with getting and displaying the data that you need. I’m sure you can already think about how this can be used with Todo apps.

Try practicing Array.filter() with examples that you create on your own, and see if you can get the exact filtered data that you want!

Sing up to get an email notification when new content is published

2 Comments

  1. Уou actually make it appear rеally easy
    with your presentation but I to fіnd this matter to be
    actᥙally something which I believe I’d never understand. It seems too complex and very
    vast for me. I am having a looҝ forward to your next post, I will attempt to get the һold of it!

    1. It can feel complex and overwhelming at first for sure.

      Try to take small steps towards it and try it with simpler concepts at first so you have a better understanding of how it works. You can start out with just trying to filter strings or numbers, play around with it and try to find ways to extract the data you need!

Leave a Reply

Your email address will not be published. Required fields are marked *

Similar Posts