Skip to content

Commit 111f0c6

Browse files
committed
PR-50377-redo-filterBooleanOverload
1 parent 3e12250 commit 111f0c6

File tree

56 files changed

+889
-143
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

56 files changed

+889
-143
lines changed

src/compiler/checker.ts

Lines changed: 26 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -14749,20 +14749,32 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1474914749
* maps primitive types and type parameters are to their apparent types.
1475014750
*/
1475114751
function getSignaturesOfType(type: Type, kind: SignatureKind): readonly Signature[] {
14752-
const result = getSignaturesOfStructuredType(getReducedApparentType(type), kind);
14753-
if (kind === SignatureKind.Call && !length(result) && type.flags & TypeFlags.Union) {
14754-
if ((type as UnionType).arrayFallbackSignatures) {
14755-
return (type as UnionType).arrayFallbackSignatures!;
14756-
}
14757-
// If the union is all different instantiations of a member of the global array type...
14758-
let memberName: __String;
14759-
if (everyType(type, t => !!t.symbol?.parent && isArrayOrTupleSymbol(t.symbol.parent) && (!memberName ? (memberName = t.symbol.escapedName, true) : memberName === t.symbol.escapedName))) {
14760-
// Transform the type from `(A[] | B[])["member"]` to `(A | B)[]["member"]` (since we pretend array is covariant anyway)
14761-
const arrayArg = mapType(type, t => getMappedType((isReadonlyArraySymbol(t.symbol.parent) ? globalReadonlyArrayType : globalArrayType).typeParameters![0], (t as AnonymousType).mapper!));
14762-
const arrayType = createArrayType(arrayArg, someType(type, t => isReadonlyArraySymbol(t.symbol.parent)));
14763-
return (type as UnionType).arrayFallbackSignatures = getSignaturesOfType(getTypeOfPropertyOfType(arrayType, memberName!)!, kind);
14764-
}
14765-
(type as UnionType).arrayFallbackSignatures = result;
14752+
function carveoutResult(type: Type, kind: SignatureKind): readonly Signature[] | undefined {
14753+
if (kind === SignatureKind.Call && type.flags & TypeFlags.Union) {
14754+
// If the union is all different instantiations of a member of the global array type...
14755+
let memberName: __String;
14756+
if (everyType(type, t => !!t.symbol?.parent && isArrayOrTupleSymbol(t.symbol.parent) && (!memberName ? (memberName = t.symbol.escapedName, true) : memberName === t.symbol.escapedName))) {
14757+
if ((type as UnionType).arrayFallbackSignatures) {
14758+
return (type as UnionType).arrayFallbackSignatures!;
14759+
}
14760+
const arrayArg = mapType(type, t => getMappedType((isReadonlyArraySymbol(t.symbol.parent) ? globalReadonlyArrayType : globalArrayType).typeParameters![0], (t as AnonymousType).mapper!));
14761+
const arrayType = createArrayType(arrayArg, someType(type, t => isReadonlyArraySymbol(t.symbol.parent)));
14762+
return (type as UnionType).arrayFallbackSignatures = getSignaturesOfType(getTypeOfPropertyOfType(arrayType, memberName!)!, kind);
14763+
}
14764+
}
14765+
return undefined;
14766+
}
14767+
let result = carveoutResult(type, kind);
14768+
if (!result) {
14769+
// although the logic here seems a bit strange, it is exactly as it was in 61a96b1641 (minus putting the carveout first),
14770+
// and changing it is beyond the scope of this pull request
14771+
result = getSignaturesOfStructuredType(getReducedApparentType(type), kind);
14772+
if (kind === SignatureKind.Call && length(result) && type.flags & TypeFlags.Union) {
14773+
if ((type as UnionType).arrayFallbackSignatures) {
14774+
return (type as UnionType).arrayFallbackSignatures!;
14775+
}
14776+
(type as UnionType).arrayFallbackSignatures = result;
14777+
}
1476614778
}
1476714779
return result;
1476814780
}

src/lib/es5.d.ts

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -536,6 +536,11 @@ interface BooleanConstructor {
536536
readonly prototype: Boolean;
537537
}
538538

539+
interface BooleanConverter {
540+
<T>(value?: T): boolean;
541+
readonly prototype: Boolean;
542+
}
543+
539544
declare var Boolean: BooleanConstructor;
540545

541546
interface Number {
@@ -1257,6 +1262,12 @@ interface ReadonlyArray<T> {
12571262
* @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.
12581263
*/
12591264
filter<S extends T>(predicate: (value: T, index: number, array: readonly T[]) => value is S, thisArg?: any): S[];
1265+
/**
1266+
* Returns the non-Falsy elements of an array
1267+
* @param predicate Must be exactly "Boolean"
1268+
* @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.
1269+
*/
1270+
filter(predicate: BooleanConverter, thisArg?: any): (T extends false | 0 | "" | null | undefined | 0n ? never : T)[];
12601271
/**
12611272
* Returns the elements of an array that meet the condition specified in a callback function.
12621273
* @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.
@@ -1448,6 +1459,12 @@ interface Array<T> {
14481459
* @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.
14491460
*/
14501461
filter<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[];
1462+
/**
1463+
* Returns the non-Falsy elements of an array
1464+
* @param predicate Must be exactly "Boolean"
1465+
* @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.
1466+
*/
1467+
filter(predicate: BooleanConverter, thisArg?: any): (T extends false | 0 | "" | null | undefined | 0n ? never : T)[];
14511468
/**
14521469
* Returns the elements of an array that meet the condition specified in a callback function.
14531470
* @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.

tests/baselines/reference/arrayFilter.symbols

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,9 +16,9 @@ var foo = [
1616
]
1717

1818
foo.filter(x => x.name); //should accepted all possible types not only boolean!
19-
>foo.filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
19+
>foo.filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
2020
>foo : Symbol(foo, Decl(arrayFilter.ts, 0, 3))
21-
>filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
21+
>filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
2222
>x : Symbol(x, Decl(arrayFilter.ts, 6, 11))
2323
>x.name : Symbol(name, Decl(arrayFilter.ts, 1, 5))
2424
>x : Symbol(x, Decl(arrayFilter.ts, 6, 11))

tests/baselines/reference/arrayFilter.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,9 +23,9 @@ var foo = [
2323

2424
foo.filter(x => x.name); //should accepted all possible types not only boolean!
2525
>foo.filter(x => x.name) : { name: string; }[]
26-
>foo.filter : { <S extends { name: string; }>(predicate: (value: { name: string; }, index: number, array: { name: string; }[]) => value is S, thisArg?: any): S[]; (predicate: (value: { name: string; }, index: number, array: { name: string; }[]) => unknown, thisArg?: any): { name: string; }[]; }
26+
>foo.filter : { <S extends { name: string; }>(predicate: (value: { name: string; }, index: number, array: { name: string; }[]) => value is S, thisArg?: any): S[]; (predicate: BooleanConverter, thisArg?: any): { name: string; }[]; (predicate: (value: { name: string; }, index: number, array: { name: string; }[]) => unknown, thisArg?: any): { name: string; }[]; }
2727
>foo : { name: string; }[]
28-
>filter : { <S extends { name: string; }>(predicate: (value: { name: string; }, index: number, array: { name: string; }[]) => value is S, thisArg?: any): S[]; (predicate: (value: { name: string; }, index: number, array: { name: string; }[]) => unknown, thisArg?: any): { name: string; }[]; }
28+
>filter : { <S extends { name: string; }>(predicate: (value: { name: string; }, index: number, array: { name: string; }[]) => value is S, thisArg?: any): S[]; (predicate: BooleanConverter, thisArg?: any): { name: string; }[]; (predicate: (value: { name: string; }, index: number, array: { name: string; }[]) => unknown, thisArg?: any): { name: string; }[]; }
2929
>x => x.name : (x: { name: string; }) => string
3030
>x : { name: string; }
3131
>x.name : string
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
//// [tests/cases/compiler/arrayFilterBooleanOverload.ts] ////
2+
3+
//// [arrayFilterBooleanOverload.ts]
4+
const nullableValues = ['a', 'b', null]; // expect (string | null)[]
5+
6+
const values1 = nullableValues.filter(Boolean); // expect string[]
7+
8+
// @ts-expect-error
9+
const values2 = nullableValues.filter(new Boolean);
10+
11+
const arr = [0, 1, "", "foo", null] as const;
12+
13+
const arr2 = arr.filter(Boolean); // expect ("foo" | 1)[]
14+
15+
16+
17+
//// [arrayFilterBooleanOverload.js]
18+
"use strict";
19+
const nullableValues = ['a', 'b', null]; // expect (string | null)[]
20+
const values1 = nullableValues.filter(Boolean); // expect string[]
21+
// @ts-expect-error
22+
const values2 = nullableValues.filter(new Boolean);
23+
const arr = [0, 1, "", "foo", null];
24+
const arr2 = arr.filter(Boolean); // expect ("foo" | 1)[]
25+
26+
27+
//// [arrayFilterBooleanOverload.d.ts]
28+
declare const nullableValues: (string | null)[];
29+
declare const values1: string[];
30+
declare const values2: (string | null)[];
31+
declare const arr: readonly [0, 1, "", "foo", null];
32+
declare const arr2: (1 | "foo")[];
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
//// [tests/cases/compiler/arrayFilterBooleanOverload.ts] ////
2+
3+
=== arrayFilterBooleanOverload.ts ===
4+
const nullableValues = ['a', 'b', null]; // expect (string | null)[]
5+
>nullableValues : Symbol(nullableValues, Decl(arrayFilterBooleanOverload.ts, 0, 5))
6+
7+
const values1 = nullableValues.filter(Boolean); // expect string[]
8+
>values1 : Symbol(values1, Decl(arrayFilterBooleanOverload.ts, 2, 5))
9+
>nullableValues.filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
10+
>nullableValues : Symbol(nullableValues, Decl(arrayFilterBooleanOverload.ts, 0, 5))
11+
>filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
12+
>Boolean : Symbol(Boolean, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
13+
14+
// @ts-expect-error
15+
const values2 = nullableValues.filter(new Boolean);
16+
>values2 : Symbol(values2, Decl(arrayFilterBooleanOverload.ts, 5, 5))
17+
>nullableValues.filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
18+
>nullableValues : Symbol(nullableValues, Decl(arrayFilterBooleanOverload.ts, 0, 5))
19+
>filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
20+
>Boolean : Symbol(Boolean, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
21+
22+
const arr = [0, 1, "", "foo", null] as const;
23+
>arr : Symbol(arr, Decl(arrayFilterBooleanOverload.ts, 7, 5))
24+
>const : Symbol(const)
25+
26+
const arr2 = arr.filter(Boolean); // expect ("foo" | 1)[]
27+
>arr2 : Symbol(arr2, Decl(arrayFilterBooleanOverload.ts, 9, 5))
28+
>arr.filter : Symbol(ReadonlyArray.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
29+
>arr : Symbol(arr, Decl(arrayFilterBooleanOverload.ts, 7, 5))
30+
>filter : Symbol(ReadonlyArray.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
31+
>Boolean : Symbol(Boolean, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
32+
33+
Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,45 @@
1+
//// [tests/cases/compiler/arrayFilterBooleanOverload.ts] ////
2+
3+
=== arrayFilterBooleanOverload.ts ===
4+
const nullableValues = ['a', 'b', null]; // expect (string | null)[]
5+
>nullableValues : (string | null)[]
6+
>['a', 'b', null] : (string | null)[]
7+
>'a' : "a"
8+
>'b' : "b"
9+
10+
const values1 = nullableValues.filter(Boolean); // expect string[]
11+
>values1 : string[]
12+
>nullableValues.filter(Boolean) : string[]
13+
>nullableValues.filter : { <S extends string | null>(predicate: (value: string | null, index: number, array: (string | null)[]) => value is S, thisArg?: any): S[]; (predicate: BooleanConverter, thisArg?: any): string[]; (predicate: (value: string | null, index: number, array: (string | null)[]) => unknown, thisArg?: any): (string | null)[]; }
14+
>nullableValues : (string | null)[]
15+
>filter : { <S extends string | null>(predicate: (value: string | null, index: number, array: (string | null)[]) => value is S, thisArg?: any): S[]; (predicate: BooleanConverter, thisArg?: any): string[]; (predicate: (value: string | null, index: number, array: (string | null)[]) => unknown, thisArg?: any): (string | null)[]; }
16+
>Boolean : BooleanConstructor
17+
18+
// @ts-expect-error
19+
const values2 = nullableValues.filter(new Boolean);
20+
>values2 : (string | null)[]
21+
>nullableValues.filter(new Boolean) : (string | null)[]
22+
>nullableValues.filter : { <S extends string | null>(predicate: (value: string | null, index: number, array: (string | null)[]) => value is S, thisArg?: any): S[]; (predicate: BooleanConverter, thisArg?: any): string[]; (predicate: (value: string | null, index: number, array: (string | null)[]) => unknown, thisArg?: any): (string | null)[]; }
23+
>nullableValues : (string | null)[]
24+
>filter : { <S extends string | null>(predicate: (value: string | null, index: number, array: (string | null)[]) => value is S, thisArg?: any): S[]; (predicate: BooleanConverter, thisArg?: any): string[]; (predicate: (value: string | null, index: number, array: (string | null)[]) => unknown, thisArg?: any): (string | null)[]; }
25+
>new Boolean : Boolean
26+
>Boolean : BooleanConstructor
27+
28+
const arr = [0, 1, "", "foo", null] as const;
29+
>arr : readonly [0, 1, "", "foo", null]
30+
>[0, 1, "", "foo", null] as const : readonly [0, 1, "", "foo", null]
31+
>[0, 1, "", "foo", null] : readonly [0, 1, "", "foo", null]
32+
>0 : 0
33+
>1 : 1
34+
>"" : ""
35+
>"foo" : "foo"
36+
37+
const arr2 = arr.filter(Boolean); // expect ("foo" | 1)[]
38+
>arr2 : (1 | "foo")[]
39+
>arr.filter(Boolean) : (1 | "foo")[]
40+
>arr.filter : { <S extends "" | 0 | 1 | "foo" | null>(predicate: (value: "" | 0 | 1 | "foo" | null, index: number, array: readonly ("" | 0 | 1 | "foo" | null)[]) => value is S, thisArg?: any): S[]; (predicate: BooleanConverter, thisArg?: any): (1 | "foo")[]; (predicate: (value: "" | 0 | 1 | "foo" | null, index: number, array: readonly ("" | 0 | 1 | "foo" | null)[]) => unknown, thisArg?: any): ("" | 0 | 1 | "foo" | null)[]; }
41+
>arr : readonly [0, 1, "", "foo", null]
42+
>filter : { <S extends "" | 0 | 1 | "foo" | null>(predicate: (value: "" | 0 | 1 | "foo" | null, index: number, array: readonly ("" | 0 | 1 | "foo" | null)[]) => value is S, thisArg?: any): S[]; (predicate: BooleanConverter, thisArg?: any): (1 | "foo")[]; (predicate: (value: "" | 0 | 1 | "foo" | null, index: number, array: readonly ("" | 0 | 1 | "foo" | null)[]) => unknown, thisArg?: any): ("" | 0 | 1 | "foo" | null)[]; }
43+
>Boolean : BooleanConstructor
44+
45+

tests/baselines/reference/arraySlice.types

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ var arr: string[] | number[];
55
>arr : string[] | number[]
66

77
arr.splice(1, 1);
8-
>arr.splice(1, 1) : string[] | number[]
8+
>arr.splice(1, 1) : (string | number)[]
99
>arr.splice : { (start: number, deleteCount?: number): string[]; (start: number, deleteCount: number, ...items: string[]): string[]; } | { (start: number, deleteCount?: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; }
1010
>arr : string[] | number[]
1111
>splice : { (start: number, deleteCount?: number): string[]; (start: number, deleteCount: number, ...items: string[]): string[]; } | { (start: number, deleteCount?: number): number[]; (start: number, deleteCount: number, ...items: number[]): number[]; }

tests/baselines/reference/bestChoiceType.symbols

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,9 @@
99
>match : Symbol(String.match, Decl(lib.es5.d.ts, --, --))
1010
>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
1111
>s : Symbol(s, Decl(bestChoiceType.ts, 2, 26))
12+
>s.toLowerCase : Symbol(String.toLowerCase, Decl(lib.es5.d.ts, --, --))
1213
>s : Symbol(s, Decl(bestChoiceType.ts, 2, 26))
14+
>toLowerCase : Symbol(String.toLowerCase, Decl(lib.es5.d.ts, --, --))
1315

1416
// Similar cases
1517

@@ -31,7 +33,9 @@ function f1() {
3133
>y : Symbol(y, Decl(bestChoiceType.ts, 8, 7))
3234
>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
3335
>s : Symbol(s, Decl(bestChoiceType.ts, 9, 18))
36+
>s.toLowerCase : Symbol(String.toLowerCase, Decl(lib.es5.d.ts, --, --))
3437
>s : Symbol(s, Decl(bestChoiceType.ts, 9, 18))
38+
>toLowerCase : Symbol(String.toLowerCase, Decl(lib.es5.d.ts, --, --))
3539
}
3640

3741
function f2() {
@@ -53,6 +57,8 @@ function f2() {
5357
>y : Symbol(y, Decl(bestChoiceType.ts, 14, 7))
5458
>map : Symbol(Array.map, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
5559
>s : Symbol(s, Decl(bestChoiceType.ts, 15, 18))
60+
>s.toLowerCase : Symbol(String.toLowerCase, Decl(lib.es5.d.ts, --, --))
5661
>s : Symbol(s, Decl(bestChoiceType.ts, 15, 18))
62+
>toLowerCase : Symbol(String.toLowerCase, Decl(lib.es5.d.ts, --, --))
5763
}
5864

tests/baselines/reference/bestChoiceType.types

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@
44
// Repro from #10041
55

66
(''.match(/ /) || []).map(s => s.toLowerCase());
7-
>(''.match(/ /) || []).map(s => s.toLowerCase()) : any[]
7+
>(''.match(/ /) || []).map(s => s.toLowerCase()) : string[]
88
>(''.match(/ /) || []).map : (<U>(callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[]) | (<U>(callbackfn: (value: never, index: number, array: never[]) => U, thisArg?: any) => U[])
99
>(''.match(/ /) || []) : RegExpMatchArray | []
1010
>''.match(/ /) || [] : RegExpMatchArray | []
@@ -15,12 +15,12 @@
1515
>/ / : RegExp
1616
>[] : []
1717
>map : (<U>(callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[]) | (<U>(callbackfn: (value: never, index: number, array: never[]) => U, thisArg?: any) => U[])
18-
>s => s.toLowerCase() : (s: any) => any
19-
>s : any
20-
>s.toLowerCase() : any
21-
>s.toLowerCase : any
22-
>s : any
23-
>toLowerCase : any
18+
>s => s.toLowerCase() : (s: string) => string
19+
>s : string
20+
>s.toLowerCase() : string
21+
>s.toLowerCase : () => string
22+
>s : string
23+
>toLowerCase : () => string
2424

2525
// Similar cases
2626

@@ -42,17 +42,17 @@ function f1() {
4242
>[] : []
4343

4444
let z = y.map(s => s.toLowerCase());
45-
>z : any[]
46-
>y.map(s => s.toLowerCase()) : any[]
45+
>z : string[]
46+
>y.map(s => s.toLowerCase()) : string[]
4747
>y.map : (<U>(callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[]) | (<U>(callbackfn: (value: never, index: number, array: never[]) => U, thisArg?: any) => U[])
4848
>y : RegExpMatchArray | []
4949
>map : (<U>(callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[]) | (<U>(callbackfn: (value: never, index: number, array: never[]) => U, thisArg?: any) => U[])
50-
>s => s.toLowerCase() : (s: any) => any
51-
>s : any
52-
>s.toLowerCase() : any
53-
>s.toLowerCase : any
54-
>s : any
55-
>toLowerCase : any
50+
>s => s.toLowerCase() : (s: string) => string
51+
>s : string
52+
>s.toLowerCase() : string
53+
>s.toLowerCase : () => string
54+
>s : string
55+
>toLowerCase : () => string
5656
}
5757

5858
function f2() {
@@ -74,16 +74,16 @@ function f2() {
7474
>[] : never[]
7575

7676
let z = y.map(s => s.toLowerCase());
77-
>z : any[]
78-
>y.map(s => s.toLowerCase()) : any[]
77+
>z : string[]
78+
>y.map(s => s.toLowerCase()) : string[]
7979
>y.map : (<U>(callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[]) | (<U>(callbackfn: (value: never, index: number, array: never[]) => U, thisArg?: any) => U[])
8080
>y : RegExpMatchArray | never[]
8181
>map : (<U>(callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[]) | (<U>(callbackfn: (value: never, index: number, array: never[]) => U, thisArg?: any) => U[])
82-
>s => s.toLowerCase() : (s: any) => any
83-
>s : any
84-
>s.toLowerCase() : any
85-
>s.toLowerCase : any
86-
>s : any
87-
>toLowerCase : any
82+
>s => s.toLowerCase() : (s: string) => string
83+
>s : string
84+
>s.toLowerCase() : string
85+
>s.toLowerCase : () => string
86+
>s : string
87+
>toLowerCase : () => string
8888
}
8989

0 commit comments

Comments
 (0)