I have a function written in typescript which takes an array of type (T | undefined)[]
and filters out all undefined values, so that the resulting type is only T.
function filterUndefined<T>(ts: (T | undefined)[]): T[] {
return ts.filter((t: T | undefined): t is T => t !== undefined);
}
This works fine, but i'd like to add that to the array prototype. Is is possible to do that and have the typings correct?
When i try to do it like this:
declare global {
interface Array<T> {
filterUndefined: () => Array<T>
}
}
Array.prototype.filterUndefined = () => {
return this.filter(x !== undefined)
};
T includes undefined and so i don't have the advantage, that the resulting type has no undefined in it.
Using
interface Array<T | undefined> {
filterUndefined: () => Array<T>;
}
seems to be no valid TS code.
Is it even possible to do what i want?
You can use the Exclude<T, U>
utility in the return type:
declare global {
interface Array<T> {
filterUndefined: () => Array<Exclude<T, undefined>>;
}
}
Your implementation should also use function () {
instead of () => {
so it can have this
refer to the array itself (otherwise, it refers to globalThis
).
Array.prototype.filterUndefined = function () {
return this.filter((x) => x !== undefined);
};
Now, it'll filter out undefined
from the array type:
const filtered = ["string", undefined].filterUndefined();
// ^? string[]
Please see Why is it frowned upon to modify JavaScript object's prototypes?