I'm still very new to TypeScript. Working on a Next.js project I am displaying a list of grouped items with titles. If there are no items in the group meeting a specific criteria, I don't want to display the title or the items. I've used the Kotlin Array.any()
function before as a way of saying "if any item matches this criteria, include it". I haven't found a way to do this in TypeScript directly. In the example below, I'd like to keep the Item
list if any of it's items have a someProp = null
. The only way I've found to do this, so far, is using !Array.every()
but the double negative "not every item.someProp not null" is really heavy on the cognitive complexity. Is there a better way to accomplish this?
{Object.entries(groupedListData!)
.filter(
([key, itemsGroupedByKey]) =>
!itemsGroupedByKey.every(
(item) => item.someProp !== null
)
)
...
I've read over all of the Array functions and none of them seem to really fit. I've also read about extending the built-in Array class with my own any()
but that seems a bit heavy-handed. I won't need this for more than a few spots in the code.
You can use the some
(MDN Docs) method to achieve this. So, in your above example, you could do something like:
Object.entries(groupedListData!)
.filter(
([key, itemsGroupedByKey]) =>
itemsGroupedByKey.some(
(item) => item.someProp === null
)
)
Just for added learning, I have included a generic version of the function so that you can reuse it as you mentioned you need it elsewhere. The TS feature I have used here is called Generic Type Variable, which will allow you to reuse filterEntries
on any kind of grouped data.
const filterEntries = <T>(
group: Record<string, T[]>,
predicate: (item: T) => boolean,
) => Object
.entries(group)
.filter(([_, items]) => items.some(predicate));
const filteredEntries = filterEntries(groupedListData!, (item) => item.someProp === null);