TypeScript Version: 2.2.2
Code
function isNumber(x: any): x is number { return typeof(x) === "number"; }
let numbersOrStrings: (number | string)[] = [1, 2, 3, 4];
if(numbersOrStrings.every(isNumber)) {
let _numbers: number[] = numbersOrStrings;
// ...
}
Expected behavior:
When every member of numberOfStrings matches the isNumber type guard, the whole array should be inferred to be numberOfStrings: number[]; so, the above code should compile without error.
Actual behavior:
The above fails to compile, with the following error:
error TS2322: Type '(string | number)[]' is not assignable to type 'number[]'.
This issue is similar to #7657, and it can be solved by adding something like the following to lib.d.ts:
interface Array<T> {
every<U extends T>(pred: (a: T) => a is U): this is U[];
}
(or, the above can be added locally to a project as a temporary workaround)
This issue is similar to #7657,
It's not the same, though. filter creates a new array, every doesn't. Assigning (string | number)[] to a number[] is unsafe, because a string can be pushed at any moment.
@vkurchatkin Would adding the above declaration for ReadonlyArray<T> be safe, then?
@kylewlacy yes, I think so
Most helpful comment
It's not the same, though.
filtercreates a new array,everydoesn't. Assigning(string | number)[]to anumber[]is unsafe, because a string can be pushed at any moment.