How to filter out undefined from array in ts?
- typescript
- filter-undefined
- tips
- use-queries-filter
So you want to filter out undefined from an array
But it keeps telling you that the result is an union of undefined | T
.
You might be tempted to use filter + map combo and a type guard along the way.
For a real world scenario let's use react-query.
It would roughly look like this.
Some starter code for react query.
import axios from "axios";
import { useQueries } from "@tanstack/react-query";
export type Todo = {
id: number;
todo: string;
completed: boolean;
userId: number;
};
async function fetchTodo(id: string): Promise {
const { data } = await axios.get(`https://dummyjson.com/todos/${id}`);
return data;
}
export function useTodoQueries(ids: string[]) {
return useQueries({
queries: ids.map((id) => {
return {
queryKey: ["todo", id],
queryFn: () => fetchTodo(id),
};
}),
});
}
Let's create queries based on ids from 1 to 10.
export type Todo = {
id: number;
todo: string;
completed: boolean;
userId: number;
};
const whateverIds = new Array(10)
.fill(0)
.map((_, index) => (index + 1).toString());
const todoQueries = useTodoQueries(whateverIds);
Let's get only defined todos from the queries the usual way
function filterAndMapResults(todoQueries: ReturnType) {
// why check the type manually 🤖 Let's use ReturnType 🥸
return (
todoQueries
// first map only the queries which have succedded
.map((q) => q.data)
// then coerce typescript with a type-guard so that data resolves as TODO
.filter((data): data is Todo => {
return !!data;
})
);
}
Let's see now how reduce can work in our favor here
function reduceResults(todoQueries: ReturnType) {
// why check the type manually 🤖 Let's use ReturnType 🥸
const initialValue: Todo[] = [];
return todoQueries.reduce((acc, current) => {
if (current.data) {
// only if data is defined add it into the result
return acc.concat(current.data);
}
// otherwise return the previous accumulator
return acc;
}, initialValue);
}
Performance concerns
For those who would be on the border here; let me explain myself.
I was not able to get constant results using the performance tab, but reduce version seemed to be around 0.1 ms slower when using 6x throttle (usually).
It's probably connected to the fact that each time a new place in memory has to be created for the brand new array.
On the other hand such concerns are rarely a thing for product devs'.
Let's face it a vast majority of time taken scripting in our apps is framework code.
Conclusion
My personal preference is the reduce way. Choose whichever way you prefer.
Remember!
Premature optimization is not what your employer wants you to take care of, your time is worth a lot 🐰.