Issue
I'm trying to figure out how to type this fmap function I have. Here's my latest attempt:
export const __skip__ = Symbol('skip');
type ReduceFn<T> = Array<T>['reduce']
/**
* Filter-map. Like map, but you may omit entries by returning `__skip__`.
*/
export function fmap<TVal,TReturn>(this:TVal[], callback: (this: TVal[], ...args:[currentValue: TVal, index: number])=>TReturn|typeof __skip__): TReturn[] {
return Array.prototype.reduce.call(this, (accum: TReturn[], ...args) => {
let x = callback.call(this, ...args);
if (x !== __skip__) {
accum.push(x);
}
return accum;
}, []);
}
It's saying x is unknown
Even though it knows what callback returns:
How come? How do I fix the errors?
N.B. I typed args as [currentValue: TVal, index: number] to try to simplify a bit, but I think it should be Parameters<ReduceFn<TVal>>
Also, I know the signature is a bit funny. The usage of this is intentional for legacy reasons.
Here's an example usage:
const keys = fmap.call(feeIds, id => feeIdToKey[id] || __skip__)
Solution
Seems like the method Array.prototype.reduce.call is trying to infer the type automatically based on the generic type of Array, but is unable to infer it properly since the default generic type of Array is any (that is Array<any>). But you can pass in whichever generic type you want to the method call, manually, rather than relying on the automatic inference in this specific instance.
Here's how you can do it:
export function fmap<TVal, TReturn>(this: TVal[], callback: (this: TVal[], ...args: [currentValue: TVal, index: number, array: TVal[]]) => TReturn | typeof __skip__): TReturn[] {
return Array.prototype.reduce.call<
// Here's our manually passed in generic type
TVal[], [callbackfn: (previousValue: TReturn[], currentValue: TVal, currentIndex: number, array: TVal[]) => TReturn[], initialValue: TReturn[]], TReturn[]
>(this, (accum: TReturn[], ...args) => {
let x = callback.call(this, ...args);
if (x !== __skip__) {
accum.push(x);
}
return accum;
}, []);
};
NOTE
I also had to add the parameter array: TVal[] to this line: callback: (this: TVal[], ...args: [currentValue: TVal, index: number, array: TVal[]]) => TReturn | typeof __skip__, since Array.prototype.reduce's callback param expects also a fourth, array, parameter.
Answered By - Kapobajza


0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.