Search code examples
typescriptundefinedprototype

Add typed function to array prototype


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?


Solution

  • 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?