Вполне себе оптимальное. Перебирается ровно столько сколько нужно.
Разве что вынести значение в переменную, чтоб лишний раз toLowerCase не делать:
function solution(a) {
return a.filter(item => filterBy.some(prop => {
const value = item[prop].toLowerCase();
return filterVal.some(i => value.includes(i));
}));
}
console.log(solution(arr));