0

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?

pietsch
  • 50
  • 7

1 Answers1

0

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[]

Playground


Please see Why is it frowned upon to modify JavaScript object's prototypes?

kelsny
  • 23,009
  • 3
  • 19
  • 48