Skip to content

Commit ccf38f6

Browse files
committed
Add this-parameter workaround to Array.filter
Allows anys.filter(Boolean) to once again return any[], not unknown[].
1 parent 3745694 commit ccf38f6

12 files changed

+199
-7
lines changed

src/lib/es5.d.ts

+6
Original file line numberDiff line numberDiff line change
@@ -1133,6 +1133,12 @@ interface ReadonlyArray<T> {
11331133
* @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.
11341134
*/
11351135
map<U>(callbackfn: (value: T, index: number, array: ReadonlyArray<T>) => U, thisArg?: any): U[];
1136+
/**
1137+
* Returns the elements of an array that meet the condition specified in a callback function.
1138+
* @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array.
1139+
* @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.
1140+
*/
1141+
filter(this: any[], callbackfn: (value: any, index: number, array: ReadonlyArray<any>) => unknown, thisArg?: any): any[];
11361142
/**
11371143
* Returns the elements of an array that meet the condition specified in a callback function.
11381144
* @param callbackfn A function that accepts up to three arguments. The filter method calls the callbackfn function one time for each element in the array.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
tests/cases/compiler/booleanFilterAnyArray.ts(14,5): error TS2403: Subsequent variable declarations must have the same type. Variable 'xs' must be of type 'Ari<any>', but here has type 'Ari<unknown>'.
2+
3+
4+
==== tests/cases/compiler/booleanFilterAnyArray.ts (1 errors) ====
5+
interface Bullean { }
6+
interface BulleanConstructor {
7+
new(v1?: any): Bullean;
8+
<T>(v2?: T): v2 is T;
9+
}
10+
11+
interface Ari<T> {
12+
filter<S extends T>(cb1: (value: T) => value is S): Ari<S>;
13+
filter(cb2: (value: T) => unknown): Ari<T>;
14+
}
15+
declare var Bullean: BulleanConstructor;
16+
declare let anys: Ari<any>;
17+
var xs: Ari<any>;
18+
var xs = anys.filter(Bullean)
19+
~~
20+
!!! error TS2403: Subsequent variable declarations must have the same type. Variable 'xs' must be of type 'Ari<any>', but here has type 'Ari<unknown>'.
21+
22+
declare let realanys: any[];
23+
var ys = realanys.filter(Boolean)
24+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//// [booleanFilterAnyArray.ts]
2+
interface Bullean { }
3+
interface BulleanConstructor {
4+
new(v1?: any): Bullean;
5+
<T>(v2?: T): v2 is T;
6+
}
7+
8+
interface Ari<T> {
9+
filter<S extends T>(cb1: (value: T) => value is S): Ari<S>;
10+
filter(cb2: (value: T) => unknown): Ari<T>;
11+
}
12+
declare var Bullean: BulleanConstructor;
13+
declare let anys: Ari<any>;
14+
var xs: Ari<any>;
15+
var xs = anys.filter(Bullean)
16+
17+
declare let realanys: any[];
18+
var ys = realanys.filter(Boolean)
19+
20+
21+
//// [booleanFilterAnyArray.js]
22+
var xs;
23+
var xs = anys.filter(Bullean);
24+
var ys = realanys.filter(Boolean);
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
=== tests/cases/compiler/booleanFilterAnyArray.ts ===
2+
interface Bullean { }
3+
>Bullean : Symbol(Bullean, Decl(booleanFilterAnyArray.ts, 0, 0), Decl(booleanFilterAnyArray.ts, 10, 11))
4+
5+
interface BulleanConstructor {
6+
>BulleanConstructor : Symbol(BulleanConstructor, Decl(booleanFilterAnyArray.ts, 0, 21))
7+
8+
new(v1?: any): Bullean;
9+
>v1 : Symbol(v1, Decl(booleanFilterAnyArray.ts, 2, 8))
10+
>Bullean : Symbol(Bullean, Decl(booleanFilterAnyArray.ts, 0, 0), Decl(booleanFilterAnyArray.ts, 10, 11))
11+
12+
<T>(v2?: T): v2 is T;
13+
>T : Symbol(T, Decl(booleanFilterAnyArray.ts, 3, 5))
14+
>v2 : Symbol(v2, Decl(booleanFilterAnyArray.ts, 3, 8))
15+
>T : Symbol(T, Decl(booleanFilterAnyArray.ts, 3, 5))
16+
>v2 : Symbol(v2, Decl(booleanFilterAnyArray.ts, 3, 8))
17+
>T : Symbol(T, Decl(booleanFilterAnyArray.ts, 3, 5))
18+
}
19+
20+
interface Ari<T> {
21+
>Ari : Symbol(Ari, Decl(booleanFilterAnyArray.ts, 4, 1))
22+
>T : Symbol(T, Decl(booleanFilterAnyArray.ts, 6, 14))
23+
24+
filter<S extends T>(cb1: (value: T) => value is S): Ari<S>;
25+
>filter : Symbol(Ari.filter, Decl(booleanFilterAnyArray.ts, 6, 18), Decl(booleanFilterAnyArray.ts, 7, 63))
26+
>S : Symbol(S, Decl(booleanFilterAnyArray.ts, 7, 11))
27+
>T : Symbol(T, Decl(booleanFilterAnyArray.ts, 6, 14))
28+
>cb1 : Symbol(cb1, Decl(booleanFilterAnyArray.ts, 7, 24))
29+
>value : Symbol(value, Decl(booleanFilterAnyArray.ts, 7, 30))
30+
>T : Symbol(T, Decl(booleanFilterAnyArray.ts, 6, 14))
31+
>value : Symbol(value, Decl(booleanFilterAnyArray.ts, 7, 30))
32+
>S : Symbol(S, Decl(booleanFilterAnyArray.ts, 7, 11))
33+
>Ari : Symbol(Ari, Decl(booleanFilterAnyArray.ts, 4, 1))
34+
>S : Symbol(S, Decl(booleanFilterAnyArray.ts, 7, 11))
35+
36+
filter(cb2: (value: T) => unknown): Ari<T>;
37+
>filter : Symbol(Ari.filter, Decl(booleanFilterAnyArray.ts, 6, 18), Decl(booleanFilterAnyArray.ts, 7, 63))
38+
>cb2 : Symbol(cb2, Decl(booleanFilterAnyArray.ts, 8, 11))
39+
>value : Symbol(value, Decl(booleanFilterAnyArray.ts, 8, 17))
40+
>T : Symbol(T, Decl(booleanFilterAnyArray.ts, 6, 14))
41+
>Ari : Symbol(Ari, Decl(booleanFilterAnyArray.ts, 4, 1))
42+
>T : Symbol(T, Decl(booleanFilterAnyArray.ts, 6, 14))
43+
}
44+
declare var Bullean: BulleanConstructor;
45+
>Bullean : Symbol(Bullean, Decl(booleanFilterAnyArray.ts, 0, 0), Decl(booleanFilterAnyArray.ts, 10, 11))
46+
>BulleanConstructor : Symbol(BulleanConstructor, Decl(booleanFilterAnyArray.ts, 0, 21))
47+
48+
declare let anys: Ari<any>;
49+
>anys : Symbol(anys, Decl(booleanFilterAnyArray.ts, 11, 11))
50+
>Ari : Symbol(Ari, Decl(booleanFilterAnyArray.ts, 4, 1))
51+
52+
var xs: Ari<any>;
53+
>xs : Symbol(xs, Decl(booleanFilterAnyArray.ts, 12, 3), Decl(booleanFilterAnyArray.ts, 13, 3))
54+
>Ari : Symbol(Ari, Decl(booleanFilterAnyArray.ts, 4, 1))
55+
56+
var xs = anys.filter(Bullean)
57+
>xs : Symbol(xs, Decl(booleanFilterAnyArray.ts, 12, 3), Decl(booleanFilterAnyArray.ts, 13, 3))
58+
>anys.filter : Symbol(Ari.filter, Decl(booleanFilterAnyArray.ts, 6, 18), Decl(booleanFilterAnyArray.ts, 7, 63))
59+
>anys : Symbol(anys, Decl(booleanFilterAnyArray.ts, 11, 11))
60+
>filter : Symbol(Ari.filter, Decl(booleanFilterAnyArray.ts, 6, 18), Decl(booleanFilterAnyArray.ts, 7, 63))
61+
>Bullean : Symbol(Bullean, Decl(booleanFilterAnyArray.ts, 0, 0), Decl(booleanFilterAnyArray.ts, 10, 11))
62+
63+
declare let realanys: any[];
64+
>realanys : Symbol(realanys, Decl(booleanFilterAnyArray.ts, 15, 11))
65+
66+
var ys = realanys.filter(Boolean)
67+
>ys : Symbol(ys, Decl(booleanFilterAnyArray.ts, 16, 3))
68+
>realanys.filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
69+
>realanys : Symbol(realanys, Decl(booleanFilterAnyArray.ts, 15, 11))
70+
>filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
71+
>Boolean : Symbol(Boolean, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
72+
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,49 @@
1+
=== tests/cases/compiler/booleanFilterAnyArray.ts ===
2+
interface Bullean { }
3+
interface BulleanConstructor {
4+
new(v1?: any): Bullean;
5+
>v1 : any
6+
7+
<T>(v2?: T): v2 is T;
8+
>v2 : T
9+
}
10+
11+
interface Ari<T> {
12+
filter<S extends T>(cb1: (value: T) => value is S): Ari<S>;
13+
>filter : { <S extends T>(cb1: (value: T) => value is S): Ari<S>; (cb2: (value: T) => unknown): Ari<T>; }
14+
>cb1 : (value: T) => value is S
15+
>value : T
16+
17+
filter(cb2: (value: T) => unknown): Ari<T>;
18+
>filter : { <S extends T>(cb1: (value: T) => value is S): Ari<S>; (cb2: (value: T) => unknown): Ari<T>; }
19+
>cb2 : (value: T) => unknown
20+
>value : T
21+
}
22+
declare var Bullean: BulleanConstructor;
23+
>Bullean : BulleanConstructor
24+
25+
declare let anys: Ari<any>;
26+
>anys : Ari<any>
27+
28+
var xs: Ari<any>;
29+
>xs : Ari<any>
30+
31+
var xs = anys.filter(Bullean)
32+
>xs : Ari<any>
33+
>anys.filter(Bullean) : Ari<unknown>
34+
>anys.filter : { <S extends any>(cb1: (value: any) => value is S): Ari<S>; (cb2: (value: any) => unknown): Ari<any>; }
35+
>anys : Ari<any>
36+
>filter : { <S extends any>(cb1: (value: any) => value is S): Ari<S>; (cb2: (value: any) => unknown): Ari<any>; }
37+
>Bullean : BulleanConstructor
38+
39+
declare let realanys: any[];
40+
>realanys : any[]
41+
42+
var ys = realanys.filter(Boolean)
43+
>ys : unknown[]
44+
>realanys.filter(Boolean) : unknown[]
45+
>realanys.filter : { <S extends any>(callbackfn: (value: any, index: number, array: any[]) => value is S, thisArg?: any): S[]; (callbackfn: (value: any, index: number, array: any[]) => unknown, thisArg?: any): any[]; }
46+
>realanys : any[]
47+
>filter : { <S extends any>(callbackfn: (value: any, index: number, array: any[]) => value is S, thisArg?: any): S[]; (callbackfn: (value: any, index: number, array: any[]) => unknown, thisArg?: any): any[]; }
48+
>Boolean : BooleanConstructor
49+

tests/baselines/reference/destructuringParameterDeclaration4.errors.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ tests/cases/conformance/es6/destructuring/destructuringParameterDeclaration4.ts(
4141
a1(...array2); // Error parameter type is (number|string)[]
4242
~~~~~~
4343
!!! error TS2552: Cannot find name 'array2'. Did you mean 'Array'?
44-
!!! related TS2728 /.ts/lib.es5.d.ts:1368:13: 'Array' is declared here.
44+
!!! related TS2728 /.ts/lib.es5.d.ts:1374:13: 'Array' is declared here.
4545
a5([1, 2, "string", false, true]); // Error, parameter type is [any, any, [[any]]]
4646
~~~~~~~~
4747
!!! error TS2322: Type 'string' is not assignable to type '[[any]]'.

tests/baselines/reference/promisePermutations.errors.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -295,7 +295,7 @@ tests/cases/compiler/promisePermutations.ts(160,21): error TS2345: Argument of t
295295
~~~~~~~~~
296296
!!! error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => Promise<number>'.
297297
!!! error TS2345: Property 'catch' is missing in type 'IPromise<string>' but required in type 'Promise<number>'.
298-
!!! related TS2728 /.ts/lib.es5.d.ts:1413:5: 'catch' is declared here.
298+
!!! related TS2728 /.ts/lib.es5.d.ts:1419:5: 'catch' is declared here.
299299
var s10g = s10.then(testFunctionP, nIPromise, sIPromise).then(sPromise, sIPromise, sIPromise); // ok
300300

301301
var r11: IPromise<number>;

tests/baselines/reference/promisePermutations2.errors.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -294,7 +294,7 @@ tests/cases/compiler/promisePermutations2.ts(159,21): error TS2345: Argument of
294294
~~~~~~~~~
295295
!!! error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => Promise<number>'.
296296
!!! error TS2345: Property 'catch' is missing in type 'IPromise<string>' but required in type 'Promise<number>'.
297-
!!! related TS2728 /.ts/lib.es5.d.ts:1413:5: 'catch' is declared here.
297+
!!! related TS2728 /.ts/lib.es5.d.ts:1419:5: 'catch' is declared here.
298298
var s10g = s10.then(testFunctionP, nIPromise, sIPromise).then(sPromise, sIPromise, sIPromise); // ok
299299

300300
var r11: IPromise<number>;

tests/baselines/reference/promisePermutations3.errors.txt

+2-2
Original file line numberDiff line numberDiff line change
@@ -303,7 +303,7 @@ tests/cases/compiler/promisePermutations3.ts(165,21): error TS2345: Argument of
303303
~~~~~~~~~
304304
!!! error TS2345: Argument of type '(x: any) => IPromise<string>' is not assignable to parameter of type '(error: any) => Promise<number>'.
305305
!!! error TS2345: Property 'catch' is missing in type 'IPromise<string>' but required in type 'Promise<number>'.
306-
!!! related TS2728 /.ts/lib.es5.d.ts:1413:5: 'catch' is declared here.
306+
!!! related TS2728 /.ts/lib.es5.d.ts:1419:5: 'catch' is declared here.
307307
var s10g = s10.then(testFunctionP, nIPromise, sIPromise).then(sPromise, sIPromise, sIPromise); // ok
308308

309309
var r11: IPromise<number>;
@@ -340,5 +340,5 @@ tests/cases/compiler/promisePermutations3.ts(165,21): error TS2345: Argument of
340340
~~~~~~~~~~~~~~~
341341
!!! error TS2345: Argument of type '{ <T>(x: T): IPromise<T>; <T>(x: T, y: T): Promise<T>; }' is not assignable to parameter of type '(value: (x: any) => any) => Promise<unknown>'.
342342
!!! error TS2345: Property 'catch' is missing in type 'IPromise<any>' but required in type 'Promise<unknown>'.
343-
!!! related TS2728 /.ts/lib.es5.d.ts:1413:5: 'catch' is declared here.
343+
!!! related TS2728 /.ts/lib.es5.d.ts:1419:5: 'catch' is declared here.
344344
var s12c = s12.then(testFunction12P, testFunction12, testFunction12); // ok

tests/baselines/reference/promiseTypeInference.errors.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -26,5 +26,5 @@ tests/cases/compiler/promiseTypeInference.ts(10,39): error TS2322: Type 'IPromis
2626
!!! error TS2322: Types of parameters 'success' and 'onfulfilled' are incompatible.
2727
!!! error TS2322: Type 'TResult1 | PromiseLike<TResult1>' is not assignable to type 'IPromise<TResult1 | TResult2>'.
2828
!!! error TS2322: Type 'TResult1' is not assignable to type 'IPromise<TResult1 | TResult2>'.
29-
!!! related TS6502 /.ts/lib.es5.d.ts:1406:57: The expected type comes from the return type of this signature.
29+
!!! related TS6502 /.ts/lib.es5.d.ts:1412:57: The expected type comes from the return type of this signature.
3030

tests/baselines/reference/redefineArray.errors.txt

+1-1
Original file line numberDiff line numberDiff line change
@@ -5,4 +5,4 @@ tests/cases/compiler/redefineArray.ts(1,1): error TS2741: Property 'isArray' is
55
Array = function (n:number, s:string) {return n;};
66
~~~~~
77
!!! error TS2741: Property 'isArray' is missing in type '(n: number, s: string) => number' but required in type 'ArrayConstructor'.
8-
!!! related TS2728 /.ts/lib.es5.d.ts:1364:5: 'isArray' is declared here.
8+
!!! related TS2728 /.ts/lib.es5.d.ts:1370:5: 'isArray' is declared here.
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
interface Bullean { }
2+
interface BulleanConstructor {
3+
new(v1?: any): Bullean;
4+
<T>(v2?: T): v2 is T;
5+
}
6+
7+
interface Ari<T> {
8+
filter<S extends T>(cb1: (value: T) => value is S): Ari<S>;
9+
filter(cb2: (value: T) => unknown): Ari<T>;
10+
}
11+
declare var Bullean: BulleanConstructor;
12+
declare let anys: Ari<any>;
13+
var xs: Ari<any>;
14+
var xs = anys.filter(Bullean)
15+
16+
declare let realanys: any[];
17+
var ys = realanys.filter(Boolean)

0 commit comments

Comments
 (0)