Skip to content

Commit e904d77

Browse files
committed
new es5.d.ts, checker.ts, and correponding test results
1 parent 99a88a2 commit e904d77

File tree

55 files changed

+778
-622
lines changed

Some content is hidden

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

55 files changed

+778
-622
lines changed

src/compiler/checker.ts

Lines changed: 64 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -14748,21 +14748,70 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1474814748
* Return the signatures of the given kind in the given type. Creates synthetic union signatures when necessary and
1474914749
* maps primitive types and type parameters are to their apparent types.
1475014750
*/
14751-
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;
14751+
function getSignaturesOfType(typeIn: Type, kind: SignatureKind): readonly Signature[] {
14752+
const reducedType = getReducedApparentType(typeIn);
14753+
function carveoutResult(): readonly Signature[] | undefined {
14754+
if (kind === SignatureKind.Call && reducedType.flags & TypeFlags.Union) {
14755+
// If the union is all different instantiations of a member of the global array type...
14756+
let memberName: __String;
14757+
if (everyType(reducedType, t => !!t.symbol?.parent && isArrayOrTupleSymbol(t.symbol.parent) && (!memberName ? (memberName = t.symbol.escapedName, true) : memberName === t.symbol.escapedName))) {
14758+
if ((reducedType as UnionType).arrayFallbackSignatures) {
14759+
return (reducedType as UnionType).arrayFallbackSignatures!;
14760+
}
14761+
14762+
// calculate return types as union of return types over the associated type, rather than return type associated with the union of types
14763+
const numTypes = (reducedType as UnionType).types.length;
14764+
const numSigs = (reducedType as UnionType).types[0].symbol.declarations?.length;
14765+
Debug.assert(numSigs);
14766+
const returnTypes = (new Array(numSigs).fill(/*value*/ undefined)).map((_, isig): Type | undefined => {
14767+
// getUnionType(*,UnionReduction.Subtype) doesn't detect duplicate types (unless I'm mistaken) so use set first.
14768+
const rtset = new Set<Type>();
14769+
new Array(numTypes).fill(/*value*/ undefined).forEach((_, itype) => {
14770+
// Notice we potentially generate the whole signature to get the return type.
14771+
// Maybe that could be avoided?
14772+
const callSignatures = ((reducedType as UnionType).types[itype] as ObjectType).callSignatures
14773+
?? getSignaturesOfStructuredType((reducedType as UnionType).types[itype] as ObjectType, SignatureKind.Call);
14774+
if (callSignatures[isig].typeParameters) return; // skip generic signatures, i.e. <S>
14775+
const returnType = callSignatures[isig].resolvedReturnType
14776+
?? getReturnTypeOfSignature(callSignatures[isig]);
14777+
Debug.assert(returnType);
14778+
rtset.add(returnType);
14779+
});
14780+
const art: Type[] = [];
14781+
rtset.forEach(rt => art.push(rt));
14782+
if (art.length === 0) return undefined;
14783+
if (art.length === 1) return art[0];
14784+
return getUnionType(art, UnionReduction.Subtype);
14785+
});
14786+
14787+
// Transform the type from `(A[] | B[])["member"]` to `(A | B)[]["member"]` (since we pretend array is covariant anyway)
14788+
const arrayArg = mapType(reducedType, t => getMappedType((isReadonlyArraySymbol(t.symbol.parent) ? globalReadonlyArrayType : globalArrayType).typeParameters![0], (t as AnonymousType).mapper!));
14789+
const arrayType = createArrayType(arrayArg, someType(reducedType, t => isReadonlyArraySymbol(t.symbol.parent)));
14790+
const result = getSignaturesOfType(getTypeOfPropertyOfType(arrayType, memberName!)!, kind);
14791+
14792+
returnTypes.forEach((returnType, sigidx) => {
14793+
if (returnType) result[sigidx].resolvedReturnType = returnTypes[sigidx];
14794+
});
14795+
return (reducedType as UnionType).arrayFallbackSignatures = result;
14796+
14797+
// const arrayArg = mapType(type, t => getMappedType((isReadonlyArraySymbol(t.symbol.parent) ? globalReadonlyArrayType : globalArrayType).typeParameters![0], (t as AnonymousType).mapper!));
14798+
// const arrayType = createArrayType(arrayArg, someType(type, t => isReadonlyArraySymbol(t.symbol.parent)));
14799+
// return (type as UnionType).arrayFallbackSignatures = getSignaturesOfType(getTypeOfPropertyOfType(arrayType, memberName!)!, kind);
14800+
}
14801+
}
14802+
return undefined;
14803+
}
14804+
let result = carveoutResult();
14805+
if (result) return result;
14806+
14807+
if (kind === SignatureKind.Call && reducedType.flags & TypeFlags.Union) {
14808+
if ((reducedType as UnionType).arrayFallbackSignatures) {
14809+
return (reducedType as UnionType).arrayFallbackSignatures!;
14810+
}
14811+
}
14812+
result = getSignaturesOfStructuredType(reducedType, kind);
14813+
if (kind === SignatureKind.Call && reducedType.flags & TypeFlags.Union) {
14814+
(reducedType as UnionType).arrayFallbackSignatures = result;
1476614815
}
1476714816
return result;
1476814817
}

src/lib/es5.d.ts

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1257,6 +1257,12 @@ interface ReadonlyArray<T> {
12571257
* @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.
12581258
*/
12591259
filter<S extends T>(predicate: (value: T, index: number, array: readonly T[]) => value is S, thisArg?: any): S[];
1260+
/**
1261+
* Returns the non-Falsy elements of an array
1262+
* @param predicate Must be exactly "Boolean"
1263+
* @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.
1264+
*/
1265+
filter(predicate: BooleanConstructor, thisArg?: any): (T extends false | 0 | "" | null | undefined | 0n ? never : T)[];
12601266
/**
12611267
* Returns the elements of an array that meet the condition specified in a callback function.
12621268
* @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 +1454,12 @@ interface Array<T> {
14481454
* @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.
14491455
*/
14501456
filter<S extends T>(predicate: (value: T, index: number, array: T[]) => value is S, thisArg?: any): S[];
1457+
/**
1458+
* Returns the non-Falsy elements of an array
1459+
* @param predicate Must be exactly "Boolean"
1460+
* @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.
1461+
*/
1462+
filter(predicate: BooleanConstructor, thisArg?: any): (T extends false | 0 | "" | null | undefined | 0n ? never : T)[];
14511463
/**
14521464
* Returns the elements of an array that meet the condition specified in a callback function.
14531465
* @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: BooleanConstructor, 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: BooleanConstructor, 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

tests/baselines/reference/arrayFilterBooleanOverload#56013WithoutExternalOverload.symbols

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,27 +18,27 @@ const id = <T,>() => (t: T) => !!t;
1818
>t : Symbol(t, Decl(arrayFilterBooleanOverload#56013WithoutExternalOverload.ts, 4, 22))
1919

2020
['foo', 'bar'].filter(id()); // // expect id() = (t: string) => boolean
21-
>['foo', 'bar'].filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
22-
>filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
21+
>['foo', 'bar'].filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
22+
>filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
2323
>id : Symbol(id, Decl(arrayFilterBooleanOverload#56013WithoutExternalOverload.ts, 4, 5))
2424

2525
['foo', 'bar', 1].filter(id()); // // expect id() = (t: string | number) => boolean
26-
>['foo', 'bar', 1].filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
27-
>filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
26+
>['foo', 'bar', 1].filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
27+
>filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
2828
>id : Symbol(id, Decl(arrayFilterBooleanOverload#56013WithoutExternalOverload.ts, 4, 5))
2929

3030
declare const maybe: boolean;
3131
>maybe : Symbol(maybe, Decl(arrayFilterBooleanOverload#56013WithoutExternalOverload.ts, 10, 13))
3232

3333
(maybe ? ['foo', 'bar'] : [1] ).filter(id()); // expect id() = (t: string | number) => boolean
34-
>(maybe ? ['foo', 'bar'] : [1] ).filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
34+
>(maybe ? ['foo', 'bar'] : [1] ).filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --) ... and 1 more)
3535
>maybe : Symbol(maybe, Decl(arrayFilterBooleanOverload#56013WithoutExternalOverload.ts, 10, 13))
36-
>filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
36+
>filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --) ... and 1 more)
3737
>id : Symbol(id, Decl(arrayFilterBooleanOverload#56013WithoutExternalOverload.ts, 4, 5))
3838

3939
['foo', 'bar', undefined].filter(id()); // expect id() = (t: string | undefined) => boolean
40-
>['foo', 'bar', undefined].filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
40+
>['foo', 'bar', undefined].filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
4141
>undefined : Symbol(undefined)
42-
>filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
42+
>filter : Symbol(Array.filter, Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --), Decl(lib.es5.d.ts, --, --))
4343
>id : Symbol(id, Decl(arrayFilterBooleanOverload#56013WithoutExternalOverload.ts, 4, 5))
4444

0 commit comments

Comments
 (0)