There have been numerous responses, so let's delve into the reasoning behind it.
Firstly, let's examine the original code snippet:
let someVar: Array<string>;
somevar = ["a", "b", undefined, "c"].filter((it) => !!it);
In line 1, the type of someVar
is declared as Array<string>
.
By adding an undefined
element in line 2, the type range expands from string[]
to (string | undefined)[]
.
A TypeScript error occurs because the variable is declared with one type but initialized with another.
You may argue that initializing someVar
to (string | undefined)[]
doesn't make sense since filtering out undefined
elements should retain the original type, right?
However, the implementation of the filter function sheds light on the issue:
The function returns the original type T
, even when excluding certain types during filtering.
So, what is the solution?
Utilize a custom type guard and specify the expected return type for the filter operation:
let someVar: Array<string>;
someVar = ["a", "b", undefined, "c"].filter<string>(isNotUndefined);
function isNotUndefined<T>(value: T | undefined): value is T {
return value !== undefined;
}
You might wonder why simply specifying the filter return type isn't sufficient:
let someVar: Array<string>;
someVar = ["a", "b", undefined, "c"].filter<string>((it) => it !== undefined);
The underlying issue lies within the typing requirements of the filter function being used:
/**
* Returns the elements of an array that meet the condition specified in a callback function.
* @param predicate A function that accepts up to three arguments. The filter method calls the predicate function one time for each element in the array.
* @param thisArg An object to which the this keyword can refer in the predicate function. If thisArg is omitted, undefined is used as the this value.
*/
filter<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[];
The filter function expects a type guard that specifically handles the return value, hence the need for a custom type guard for proper type inference.