Skip to content

Commit fc29212

Browse files
committed
Added overload to ReadonlyArray.prototype.every to make it a type guard if the callback is one.
Fixes microsoft#14963
1 parent 49a73a9 commit fc29212

File tree

5 files changed

+216
-0
lines changed

5 files changed

+216
-0
lines changed

src/lib/es5.d.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1014,6 +1014,7 @@ interface ReadonlyArray<T> {
10141014
* @param callbackfn A function that accepts up to three arguments. The every method calls the callbackfn function for each element in array1 until the callbackfn returns false, or until the end of the array.
10151015
* @param thisArg An object to which the this keyword can refer in the callbackfn function. If thisArg is omitted, undefined is used as the this value.
10161016
*/
1017+
every<U extends T>(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => value is U, thisArg?: any): this is ReadonlyArray<U>;
10171018
every(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => boolean, thisArg?: any): boolean;
10181019
/**
10191020
* Determines whether the specified callback function returns true for any element of an array.
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
//// [arrayEvery.ts]
2+
declare const baseReadonlyArray: ReadonlyArray<number | string>;
3+
const isNumber = (x: any): x is number => "number" === typeof x;
4+
5+
if (baseReadonlyArray.every<number>((x): x is number => "number" === typeof x)) {
6+
const numberReadonlyArray: ReadonlyArray<number> = baseReadonlyArray; // should be ReadonlyArray<number>
7+
}
8+
if (baseReadonlyArray.every<number>(isNumber)) {
9+
const numberReadonlyArray: ReadonlyArray<number> = baseReadonlyArray; // should be ReadonlyArray<number>
10+
}
11+
12+
if (baseReadonlyArray.every((x: any): x is number => "number" === typeof x)) {
13+
const numberReadonlyArray: ReadonlyArray<number> = baseReadonlyArray; // should be ReadonlyArray<number>
14+
}
15+
if (baseReadonlyArray.every(isNumber)) {
16+
const numberReadonlyArray: ReadonlyArray<number> = baseReadonlyArray; // should be ReadonlyArray<number>
17+
}
18+
19+
baseReadonlyArray.every(x => "number" === typeof x && x > 2);
20+
21+
//// [arrayEvery.js]
22+
var isNumber = function (x) { return "number" === typeof x; };
23+
if (baseReadonlyArray.every(function (x) { return "number" === typeof x; })) {
24+
var numberReadonlyArray = baseReadonlyArray; // should be ReadonlyArray<number>
25+
}
26+
if (baseReadonlyArray.every(isNumber)) {
27+
var numberReadonlyArray = baseReadonlyArray; // should be ReadonlyArray<number>
28+
}
29+
if (baseReadonlyArray.every(function (x) { return "number" === typeof x; })) {
30+
var numberReadonlyArray = baseReadonlyArray; // should be ReadonlyArray<number>
31+
}
32+
if (baseReadonlyArray.every(isNumber)) {
33+
var numberReadonlyArray = baseReadonlyArray; // should be ReadonlyArray<number>
34+
}
35+
baseReadonlyArray.every(function (x) { return "number" === typeof x && x > 2; });
Lines changed: 69 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,69 @@
1+
=== tests/cases/compiler/arrayEvery.ts ===
2+
declare const baseReadonlyArray: ReadonlyArray<number | string>;
3+
>baseReadonlyArray : Symbol(baseReadonlyArray, Decl(arrayEvery.ts, 0, 13))
4+
>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.d.ts, --, --))
5+
6+
const isNumber = (x: any): x is number => "number" === typeof x;
7+
>isNumber : Symbol(isNumber, Decl(arrayEvery.ts, 1, 5))
8+
>x : Symbol(x, Decl(arrayEvery.ts, 1, 18))
9+
>x : Symbol(x, Decl(arrayEvery.ts, 1, 18))
10+
>x : Symbol(x, Decl(arrayEvery.ts, 1, 18))
11+
12+
if (baseReadonlyArray.every<number>((x): x is number => "number" === typeof x)) {
13+
>baseReadonlyArray.every : Symbol(ReadonlyArray.every, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
14+
>baseReadonlyArray : Symbol(baseReadonlyArray, Decl(arrayEvery.ts, 0, 13))
15+
>every : Symbol(ReadonlyArray.every, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
16+
>x : Symbol(x, Decl(arrayEvery.ts, 3, 37))
17+
>x : Symbol(x, Decl(arrayEvery.ts, 3, 37))
18+
>x : Symbol(x, Decl(arrayEvery.ts, 3, 37))
19+
20+
const numberReadonlyArray: ReadonlyArray<number> = baseReadonlyArray; // should be ReadonlyArray<number>
21+
>numberReadonlyArray : Symbol(numberReadonlyArray, Decl(arrayEvery.ts, 4, 7))
22+
>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.d.ts, --, --))
23+
>baseReadonlyArray : Symbol(baseReadonlyArray, Decl(arrayEvery.ts, 0, 13))
24+
}
25+
if (baseReadonlyArray.every<number>(isNumber)) {
26+
>baseReadonlyArray.every : Symbol(ReadonlyArray.every, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
27+
>baseReadonlyArray : Symbol(baseReadonlyArray, Decl(arrayEvery.ts, 0, 13))
28+
>every : Symbol(ReadonlyArray.every, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
29+
>isNumber : Symbol(isNumber, Decl(arrayEvery.ts, 1, 5))
30+
31+
const numberReadonlyArray: ReadonlyArray<number> = baseReadonlyArray; // should be ReadonlyArray<number>
32+
>numberReadonlyArray : Symbol(numberReadonlyArray, Decl(arrayEvery.ts, 7, 7))
33+
>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.d.ts, --, --))
34+
>baseReadonlyArray : Symbol(baseReadonlyArray, Decl(arrayEvery.ts, 0, 13))
35+
}
36+
37+
if (baseReadonlyArray.every((x: any): x is number => "number" === typeof x)) {
38+
>baseReadonlyArray.every : Symbol(ReadonlyArray.every, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
39+
>baseReadonlyArray : Symbol(baseReadonlyArray, Decl(arrayEvery.ts, 0, 13))
40+
>every : Symbol(ReadonlyArray.every, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
41+
>x : Symbol(x, Decl(arrayEvery.ts, 10, 29))
42+
>x : Symbol(x, Decl(arrayEvery.ts, 10, 29))
43+
>x : Symbol(x, Decl(arrayEvery.ts, 10, 29))
44+
45+
const numberReadonlyArray: ReadonlyArray<number> = baseReadonlyArray; // should be ReadonlyArray<number>
46+
>numberReadonlyArray : Symbol(numberReadonlyArray, Decl(arrayEvery.ts, 11, 7))
47+
>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.d.ts, --, --))
48+
>baseReadonlyArray : Symbol(baseReadonlyArray, Decl(arrayEvery.ts, 0, 13))
49+
}
50+
if (baseReadonlyArray.every(isNumber)) {
51+
>baseReadonlyArray.every : Symbol(ReadonlyArray.every, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
52+
>baseReadonlyArray : Symbol(baseReadonlyArray, Decl(arrayEvery.ts, 0, 13))
53+
>every : Symbol(ReadonlyArray.every, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
54+
>isNumber : Symbol(isNumber, Decl(arrayEvery.ts, 1, 5))
55+
56+
const numberReadonlyArray: ReadonlyArray<number> = baseReadonlyArray; // should be ReadonlyArray<number>
57+
>numberReadonlyArray : Symbol(numberReadonlyArray, Decl(arrayEvery.ts, 14, 7))
58+
>ReadonlyArray : Symbol(ReadonlyArray, Decl(lib.d.ts, --, --))
59+
>baseReadonlyArray : Symbol(baseReadonlyArray, Decl(arrayEvery.ts, 0, 13))
60+
}
61+
62+
baseReadonlyArray.every(x => "number" === typeof x && x > 2);
63+
>baseReadonlyArray.every : Symbol(ReadonlyArray.every, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
64+
>baseReadonlyArray : Symbol(baseReadonlyArray, Decl(arrayEvery.ts, 0, 13))
65+
>every : Symbol(ReadonlyArray.every, Decl(lib.d.ts, --, --), Decl(lib.d.ts, --, --))
66+
>x : Symbol(x, Decl(arrayEvery.ts, 17, 24))
67+
>x : Symbol(x, Decl(arrayEvery.ts, 17, 24))
68+
>x : Symbol(x, Decl(arrayEvery.ts, 17, 24))
69+
Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
=== tests/cases/compiler/arrayEvery.ts ===
2+
declare const baseReadonlyArray: ReadonlyArray<number | string>;
3+
>baseReadonlyArray : ReadonlyArray<string | number>
4+
>ReadonlyArray : ReadonlyArray<T>
5+
6+
const isNumber = (x: any): x is number => "number" === typeof x;
7+
>isNumber : (x: any) => x is number
8+
>(x: any): x is number => "number" === typeof x : (x: any) => x is number
9+
>x : any
10+
>x : any
11+
>"number" === typeof x : boolean
12+
>"number" : "number"
13+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
14+
>x : any
15+
16+
if (baseReadonlyArray.every<number>((x): x is number => "number" === typeof x)) {
17+
>baseReadonlyArray.every<number>((x): x is number => "number" === typeof x) : boolean
18+
>baseReadonlyArray.every : { <U extends string | number>(callbackfn: (value: string | number, index: number, array: ReadonlyArray<string | number>) => value is U, thisArg?: any): this is ReadonlyArray<U>; (callbackfn: (value: string | number, index: number, array: ReadonlyArray<string | number>) => boolean, thisArg?: any): boolean; }
19+
>baseReadonlyArray : ReadonlyArray<string | number>
20+
>every : { <U extends string | number>(callbackfn: (value: string | number, index: number, array: ReadonlyArray<string | number>) => value is U, thisArg?: any): this is ReadonlyArray<U>; (callbackfn: (value: string | number, index: number, array: ReadonlyArray<string | number>) => boolean, thisArg?: any): boolean; }
21+
>(x): x is number => "number" === typeof x : (x: string | number) => x is number
22+
>x : string | number
23+
>x : any
24+
>"number" === typeof x : boolean
25+
>"number" : "number"
26+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
27+
>x : string | number
28+
29+
const numberReadonlyArray: ReadonlyArray<number> = baseReadonlyArray; // should be ReadonlyArray<number>
30+
>numberReadonlyArray : ReadonlyArray<number>
31+
>ReadonlyArray : ReadonlyArray<T>
32+
>baseReadonlyArray : ReadonlyArray<number>
33+
}
34+
if (baseReadonlyArray.every<number>(isNumber)) {
35+
>baseReadonlyArray.every<number>(isNumber) : boolean
36+
>baseReadonlyArray.every : { <U extends string | number>(callbackfn: (value: string | number, index: number, array: ReadonlyArray<string | number>) => value is U, thisArg?: any): this is ReadonlyArray<U>; (callbackfn: (value: string | number, index: number, array: ReadonlyArray<string | number>) => boolean, thisArg?: any): boolean; }
37+
>baseReadonlyArray : ReadonlyArray<string | number>
38+
>every : { <U extends string | number>(callbackfn: (value: string | number, index: number, array: ReadonlyArray<string | number>) => value is U, thisArg?: any): this is ReadonlyArray<U>; (callbackfn: (value: string | number, index: number, array: ReadonlyArray<string | number>) => boolean, thisArg?: any): boolean; }
39+
>isNumber : (x: any) => x is number
40+
41+
const numberReadonlyArray: ReadonlyArray<number> = baseReadonlyArray; // should be ReadonlyArray<number>
42+
>numberReadonlyArray : ReadonlyArray<number>
43+
>ReadonlyArray : ReadonlyArray<T>
44+
>baseReadonlyArray : ReadonlyArray<number>
45+
}
46+
47+
if (baseReadonlyArray.every((x: any): x is number => "number" === typeof x)) {
48+
>baseReadonlyArray.every((x: any): x is number => "number" === typeof x) : boolean
49+
>baseReadonlyArray.every : { <U extends string | number>(callbackfn: (value: string | number, index: number, array: ReadonlyArray<string | number>) => value is U, thisArg?: any): this is ReadonlyArray<U>; (callbackfn: (value: string | number, index: number, array: ReadonlyArray<string | number>) => boolean, thisArg?: any): boolean; }
50+
>baseReadonlyArray : ReadonlyArray<string | number>
51+
>every : { <U extends string | number>(callbackfn: (value: string | number, index: number, array: ReadonlyArray<string | number>) => value is U, thisArg?: any): this is ReadonlyArray<U>; (callbackfn: (value: string | number, index: number, array: ReadonlyArray<string | number>) => boolean, thisArg?: any): boolean; }
52+
>(x: any): x is number => "number" === typeof x : (x: any) => x is number
53+
>x : any
54+
>x : any
55+
>"number" === typeof x : boolean
56+
>"number" : "number"
57+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
58+
>x : any
59+
60+
const numberReadonlyArray: ReadonlyArray<number> = baseReadonlyArray; // should be ReadonlyArray<number>
61+
>numberReadonlyArray : ReadonlyArray<number>
62+
>ReadonlyArray : ReadonlyArray<T>
63+
>baseReadonlyArray : ReadonlyArray<number>
64+
}
65+
if (baseReadonlyArray.every(isNumber)) {
66+
>baseReadonlyArray.every(isNumber) : boolean
67+
>baseReadonlyArray.every : { <U extends string | number>(callbackfn: (value: string | number, index: number, array: ReadonlyArray<string | number>) => value is U, thisArg?: any): this is ReadonlyArray<U>; (callbackfn: (value: string | number, index: number, array: ReadonlyArray<string | number>) => boolean, thisArg?: any): boolean; }
68+
>baseReadonlyArray : ReadonlyArray<string | number>
69+
>every : { <U extends string | number>(callbackfn: (value: string | number, index: number, array: ReadonlyArray<string | number>) => value is U, thisArg?: any): this is ReadonlyArray<U>; (callbackfn: (value: string | number, index: number, array: ReadonlyArray<string | number>) => boolean, thisArg?: any): boolean; }
70+
>isNumber : (x: any) => x is number
71+
72+
const numberReadonlyArray: ReadonlyArray<number> = baseReadonlyArray; // should be ReadonlyArray<number>
73+
>numberReadonlyArray : ReadonlyArray<number>
74+
>ReadonlyArray : ReadonlyArray<T>
75+
>baseReadonlyArray : ReadonlyArray<number>
76+
}
77+
78+
baseReadonlyArray.every(x => "number" === typeof x && x > 2);
79+
>baseReadonlyArray.every(x => "number" === typeof x && x > 2) : boolean
80+
>baseReadonlyArray.every : { <U extends string | number>(callbackfn: (value: string | number, index: number, array: ReadonlyArray<string | number>) => value is U, thisArg?: any): this is ReadonlyArray<U>; (callbackfn: (value: string | number, index: number, array: ReadonlyArray<string | number>) => boolean, thisArg?: any): boolean; }
81+
>baseReadonlyArray : ReadonlyArray<string | number>
82+
>every : { <U extends string | number>(callbackfn: (value: string | number, index: number, array: ReadonlyArray<string | number>) => value is U, thisArg?: any): this is ReadonlyArray<U>; (callbackfn: (value: string | number, index: number, array: ReadonlyArray<string | number>) => boolean, thisArg?: any): boolean; }
83+
>x => "number" === typeof x && x > 2 : (x: string | number) => boolean
84+
>x : string | number
85+
>"number" === typeof x && x > 2 : boolean
86+
>"number" === typeof x : boolean
87+
>"number" : "number"
88+
>typeof x : "string" | "number" | "boolean" | "symbol" | "undefined" | "object" | "function"
89+
>x : string | number
90+
>x > 2 : boolean
91+
>x : number
92+
>2 : 2
93+

tests/cases/compiler/arrayEvery.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
declare const baseReadonlyArray: ReadonlyArray<number | string>;
2+
const isNumber = (x: any): x is number => "number" === typeof x;
3+
4+
if (baseReadonlyArray.every<number>((x): x is number => "number" === typeof x)) {
5+
const numberReadonlyArray: ReadonlyArray<number> = baseReadonlyArray; // should be ReadonlyArray<number>
6+
}
7+
if (baseReadonlyArray.every<number>(isNumber)) {
8+
const numberReadonlyArray: ReadonlyArray<number> = baseReadonlyArray; // should be ReadonlyArray<number>
9+
}
10+
11+
if (baseReadonlyArray.every((x: any): x is number => "number" === typeof x)) {
12+
const numberReadonlyArray: ReadonlyArray<number> = baseReadonlyArray; // should be ReadonlyArray<number>
13+
}
14+
if (baseReadonlyArray.every(isNumber)) {
15+
const numberReadonlyArray: ReadonlyArray<number> = baseReadonlyArray; // should be ReadonlyArray<number>
16+
}
17+
18+
baseReadonlyArray.every(x => "number" === typeof x && x > 2);

0 commit comments

Comments
 (0)