Я пытаюсь объединить методы массива filter и map в одну функцию, называемую malter. Я зашел так далеко:
type mapFn<T, S> = (value: T, index: number, originalArray: Readonly<T[]>) => S;
interface Array<T> {
malter<S = any>(mapFn: mapFn<T, S>): S[];
}
function notUndefined<T>(v: T | undefined): v is T {
return typeof v !== "undefined"
}
Array.prototype.malter = function malter<T, S = any>(mapFn: mapFn<T, S>): S[] {
return this.reduce(function(acc: S[], val: T, index: number, orgArr: T[]) {
const el = mapFn(val, index, orgArr);
if (notUndefined(el)) {
acc.push(el);
}
return acc;
}, []);
};
Это в основном работает.
Но при использовании он выдает ошибку TypeError в строке 5-7.
Другая тестовая функция, которая неявно возвращала undefined, также выдавала эту ошибку.
Type 'string | undefined' is not assignable to type 'string'.
Type 'undefined' is not assignable to type 'string'."
const test = [2, 3, 4, 5, 3];
function test1(): string[] {
return test.malter<number, string>(num =>
num > 3
? num.toFixed(2)
: undefined
);
}
Решение, которое бы работало без ошибок, - предоставить 2 аргумента для malter. Фильтр и функция карты и вызывать их отдельно. Это обеспечит сохранение типа, но также сделает его менее простым.
Конечно, я мог бы просто сделать это в строке 5-7:
(num > 3 ? num.toFixed(2) : undefined) as string
Это может быть лучшим компромиссом?
Как вы думаете? Есть ли решение, о котором я не думал, или вы идете с компромиссом?