In strict mode, TypeScript makes it illegal to assign an array of type (T | undefined) to an array of type T[]. This prevents bugs by preventing us from dotting into (de-referencing) an undefined object. It also poses a problem: how do we convince the compiler that it is okay to assign to T[] after we have removed all of the undefined array values?

The answer is a user-defined type guard.

Let's start with an example. We start with an array of type (Date | undefined)[] and then filter out all the undefined dates.

const items: (Date | undefined)[] = [new Date(), undefined];

// Type '(Date | undefined)[]' is not assignable to type 'Date[]'.
const definedItemsBad: Date[] = items
    .filter(item => typeof item !== 'undefined');

Even though we have filtered the array, the compiler cannot infer that the array has no undefined values.

Happily, a user-defined type-guard tells the compiler what we have done. In the following code, note that input is of type T | undefined | null instead of type any. That ensures that T captures only the defined part of the union type instead of capturing the whole union type of T | undefined | null. That is what lets our input is T type-guard tell the compiler that we have narrowed the type.

const isDefined = <T>(input: T | undefined | null): input is T => { 
    return typeof input !== 'undefined' && input !== null;
};

const definedItems: Date[] = items.filter(isDefined);

By way of explanation, here is the evolution from an inline, non-generic type-guard to the above finished product. For simplicity's sake, I have returned true instead of doing the actual check for undefined and null.

const definedItems1: Date[] = items.filter((input): input is Date => true);

const isDefinedDate = (input): input is Date => true;
const definedItems2: Date[] = items.filter(isDefinedDate);

const isDefinedGeneric = <T>(input: T | undefined | null): input is T => true;
const definedItems3: Date[] = items.filter(isDefinedGeneric);

Here it all is as a Fiddle.