Skip to content

Commit 9f37b5e

Browse files
committed
Avoid pulling object function property augmentations when resolving intersections' properties
1 parent bf91747 commit 9f37b5e

File tree

5 files changed

+35
-8
lines changed

5 files changed

+35
-8
lines changed

src/compiler/checker.ts

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -13483,7 +13483,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1348313483
for (const current of type.types) {
1348413484
for (const prop of getPropertiesOfType(current)) {
1348513485
if (!members.has(prop.escapedName)) {
13486-
const combinedProp = getPropertyOfUnionOrIntersectionType(type, prop.escapedName);
13486+
const combinedProp = getPropertyOfUnionOrIntersectionType(type, prop.escapedName, /*skipObjectFunctionPropertyAugment*/ !!(type.flags & TypeFlags.Intersection));
1348713487
if (combinedProp) {
1348813488
members.set(prop.escapedName, combinedProp);
1348913489
}
@@ -14268,7 +14268,17 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1426814268
}
1426914269
return getPropertyOfObjectType(globalObjectType, name);
1427014270
}
14271-
if (type.flags & TypeFlags.UnionOrIntersection) {
14271+
if (type.flags & TypeFlags.Intersection) {
14272+
const prop = getPropertyOfUnionOrIntersectionType(type as UnionOrIntersectionType, name, /*skipObjectFunctionPropertyAugment*/ true);
14273+
if (prop) {
14274+
return prop;
14275+
}
14276+
if (!skipObjectFunctionPropertyAugment) {
14277+
return getPropertyOfUnionOrIntersectionType(type as UnionOrIntersectionType, name, skipObjectFunctionPropertyAugment)
14278+
}
14279+
return undefined;
14280+
}
14281+
if (type.flags & TypeFlags.Union) {
1427214282
return getPropertyOfUnionOrIntersectionType(type as UnionOrIntersectionType, name, skipObjectFunctionPropertyAugment);
1427314283
}
1427414284
return undefined;
@@ -22351,11 +22361,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2235122361
// from the target union, across all members
2235222362
const properties = getPropertiesOfType(target);
2235322363
const numericNamesOnly = isTupleType(source) && isTupleType(target);
22354-
for (let targetProp of excludeProperties(properties, excludedProperties)) {
22364+
for (const targetProp of excludeProperties(properties, excludedProperties)) {
2235522365
const name = targetProp.escapedName;
22356-
if (target.flags & TypeFlags.Intersection) {
22357-
targetProp = getPropertyOfUnionOrIntersectionType(target as IntersectionType, name, /*skipObjectFunctionPropertyAugment*/ true) || targetProp;
22358-
}
2235922366
if (!(targetProp.flags & SymbolFlags.Prototype) && (!numericNamesOnly || isNumericLiteralName(name) || name === "length") && (!optionalsOnly || targetProp.flags & SymbolFlags.Optional)) {
2236022367
const sourceProp = getPropertyOfType(source, name);
2236122368
if (sourceProp && sourceProp !== targetProp) {

tests/baselines/reference/intersectionIncludingPropFromGlobalAugmentation.symbols

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,11 @@ const target: Test2 = { ...source };
2121
>Test2 : Symbol(Test2, Decl(intersectionIncludingPropFromGlobalAugmentation.ts, 2, 46))
2222
>source : Symbol(source, Decl(intersectionIncludingPropFromGlobalAugmentation.ts, 4, 13))
2323

24+
const toString = target.toString;
25+
>toString : Symbol(toString, Decl(intersectionIncludingPropFromGlobalAugmentation.ts, 7, 5))
26+
>target.toString : Symbol(Test1.toString, Decl(intersectionIncludingPropFromGlobalAugmentation.ts, 2, 17))
27+
>target : Symbol(target, Decl(intersectionIncludingPropFromGlobalAugmentation.ts, 5, 5))
28+
>toString : Symbol(Test1.toString, Decl(intersectionIncludingPropFromGlobalAugmentation.ts, 2, 17))
29+
30+
export {}
31+

tests/baselines/reference/intersectionIncludingPropFromGlobalAugmentation.types

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,11 @@ const target: Test2 = { ...source };
1818
>{ ...source } : { toString: "string" | null; }
1919
>source : Test1
2020

21+
const toString = target.toString;
22+
>toString : "string" | null
23+
>target.toString : "string" | null
24+
>target : Test2
25+
>toString : "string" | null
26+
27+
export {}
28+

tests/baselines/reference/mappedTypeAsClauses.types

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -35,10 +35,10 @@ type TP1 = TypeFromDefs<{ name: 'a', type: string } | { name: 'b', type: number
3535
// No array or tuple type mapping when 'as N' clause present
3636

3737
type TA1 = Getters<string[]>;
38-
>TA1 : { getConcat: () => { (...items: ConcatArray<string>[]): string[]; (...items: (string | ConcatArray<string>)[]): string[]; }; getIndexOf: () => (searchElement: string, fromIndex?: number | undefined) => number; getLastIndexOf: () => (searchElement: string, fromIndex?: number | undefined) => number; getSlice: () => (start?: number | undefined, end?: number | undefined) => string[]; getLength: () => number; getToString: () => () => string; getToLocaleString: () => () => string; getPop: () => () => string | undefined; getPush: () => (...items: string[]) => number; getJoin: () => (separator?: string | undefined) => string; getReverse: () => () => string[]; getShift: () => () => string | undefined; getSort: () => (compareFn?: ((a: string, b: string) => number) | undefined) => string[]; getSplice: () => { (start: number, deleteCount?: number | undefined): string[]; (start: number, deleteCount: number, ...items: string[]): string[]; }; getUnshift: () => (...items: string[]) => number; getEvery: () => { <S extends string>(predicate: (value: string, index: number, array: string[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: string, index: number, array: string[]) => unknown, thisArg?: any): boolean; }; getSome: () => (predicate: (value: string, index: number, array: string[]) => unknown, thisArg?: any) => boolean; getForEach: () => (callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any) => void; getMap: () => <U>(callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[]; getFilter: () => { <S extends string>(predicate: (value: string, index: number, array: string[]) => value is S, thisArg?: any): S[]; (predicate: (value: string, index: number, array: string[]) => unknown, thisArg?: any): string[]; }; getReduce: () => { (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string): string; (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string, initialValue: string): string; <U>(callbackfn: (previousValue: U, currentValue: string, currentIndex: number, array: string[]) => U, initialValue: U): U; }; getReduceRight: () => { (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string): string; (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string, initialValue: string): string; <U>(callbackfn: (previousValue: U, currentValue: string, currentIndex: number, array: string[]) => U, initialValue: U): U; }; }
38+
>TA1 : { getConcat: () => { (...items: ConcatArray<string>[]): string[]; (...items: (string | ConcatArray<string>)[]): string[]; }; getIndexOf: () => (searchElement: string, fromIndex?: number | undefined) => number; getLastIndexOf: () => (searchElement: string, fromIndex?: number | undefined) => number; getSlice: () => (start?: number | undefined, end?: number | undefined) => string[]; getLength: () => number; getToLocaleString: () => () => string; getToString: () => () => string; getPop: () => () => string | undefined; getPush: () => (...items: string[]) => number; getJoin: () => (separator?: string | undefined) => string; getReverse: () => () => string[]; getShift: () => () => string | undefined; getSort: () => (compareFn?: ((a: string, b: string) => number) | undefined) => string[]; getSplice: () => { (start: number, deleteCount?: number | undefined): string[]; (start: number, deleteCount: number, ...items: string[]): string[]; }; getUnshift: () => (...items: string[]) => number; getEvery: () => { <S extends string>(predicate: (value: string, index: number, array: string[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: string, index: number, array: string[]) => unknown, thisArg?: any): boolean; }; getSome: () => (predicate: (value: string, index: number, array: string[]) => unknown, thisArg?: any) => boolean; getForEach: () => (callbackfn: (value: string, index: number, array: string[]) => void, thisArg?: any) => void; getMap: () => <U>(callbackfn: (value: string, index: number, array: string[]) => U, thisArg?: any) => U[]; getFilter: () => { <S extends string>(predicate: (value: string, index: number, array: string[]) => value is S, thisArg?: any): S[]; (predicate: (value: string, index: number, array: string[]) => unknown, thisArg?: any): string[]; }; getReduce: () => { (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string): string; (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string, initialValue: string): string; <U>(callbackfn: (previousValue: U, currentValue: string, currentIndex: number, array: string[]) => U, initialValue: U): U; }; getReduceRight: () => { (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string): string; (callbackfn: (previousValue: string, currentValue: string, currentIndex: number, array: string[]) => string, initialValue: string): string; <U>(callbackfn: (previousValue: U, currentValue: string, currentIndex: number, array: string[]) => U, initialValue: U): U; }; }
3939

4040
type TA2 = Getters<[number, boolean]>;
41-
>TA2 : { getConcat: () => { (...items: ConcatArray<number | boolean>[]): (number | boolean)[]; (...items: (number | boolean | ConcatArray<number | boolean>)[]): (number | boolean)[]; }; getIndexOf: () => (searchElement: number | boolean, fromIndex?: number | undefined) => number; getLastIndexOf: () => (searchElement: number | boolean, fromIndex?: number | undefined) => number; getSlice: () => (start?: number | undefined, end?: number | undefined) => (number | boolean)[]; getLength: () => 2; getToString: () => () => string; getToLocaleString: () => () => string; getPop: () => () => number | boolean | undefined; getPush: () => (...items: (number | boolean)[]) => number; getJoin: () => (separator?: string | undefined) => string; getReverse: () => () => (number | boolean)[]; getShift: () => () => number | boolean | undefined; getSort: () => (compareFn?: ((a: number | boolean, b: number | boolean) => number) | undefined) => [number, boolean]; getSplice: () => { (start: number, deleteCount?: number | undefined): (number | boolean)[]; (start: number, deleteCount: number, ...items: (number | boolean)[]): (number | boolean)[]; }; getUnshift: () => (...items: (number | boolean)[]) => number; getEvery: () => { <S extends number | boolean>(predicate: (value: number | boolean, index: number, array: (number | boolean)[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: number | boolean, index: number, array: (number | boolean)[]) => unknown, thisArg?: any): boolean; }; getSome: () => (predicate: (value: number | boolean, index: number, array: (number | boolean)[]) => unknown, thisArg?: any) => boolean; getForEach: () => (callbackfn: (value: number | boolean, index: number, array: (number | boolean)[]) => void, thisArg?: any) => void; getMap: () => <U>(callbackfn: (value: number | boolean, index: number, array: (number | boolean)[]) => U, thisArg?: any) => U[]; getFilter: () => { <S extends number | boolean>(predicate: (value: number | boolean, index: number, array: (number | boolean)[]) => value is S, thisArg?: any): S[]; (predicate: (value: number | boolean, index: number, array: (number | boolean)[]) => unknown, thisArg?: any): (number | boolean)[]; }; getReduce: () => { (callbackfn: (previousValue: number | boolean, currentValue: number | boolean, currentIndex: number, array: (number | boolean)[]) => number | boolean): number | boolean; (callbackfn: (previousValue: number | boolean, currentValue: number | boolean, currentIndex: number, array: (number | boolean)[]) => number | boolean, initialValue: number | boolean): number | boolean; <U>(callbackfn: (previousValue: U, currentValue: number | boolean, currentIndex: number, array: (number | boolean)[]) => U, initialValue: U): U; }; getReduceRight: () => { (callbackfn: (previousValue: number | boolean, currentValue: number | boolean, currentIndex: number, array: (number | boolean)[]) => number | boolean): number | boolean; (callbackfn: (previousValue: number | boolean, currentValue: number | boolean, currentIndex: number, array: (number | boolean)[]) => number | boolean, initialValue: number | boolean): number | boolean; <U>(callbackfn: (previousValue: U, currentValue: number | boolean, currentIndex: number, array: (number | boolean)[]) => U, initialValue: U): U; }; get0: () => number; get1: () => boolean; }
41+
>TA2 : { getConcat: () => { (...items: ConcatArray<number | boolean>[]): (number | boolean)[]; (...items: (number | boolean | ConcatArray<number | boolean>)[]): (number | boolean)[]; }; getIndexOf: () => (searchElement: number | boolean, fromIndex?: number | undefined) => number; getLastIndexOf: () => (searchElement: number | boolean, fromIndex?: number | undefined) => number; getSlice: () => (start?: number | undefined, end?: number | undefined) => (number | boolean)[]; getLength: () => 2; getToLocaleString: () => () => string; getToString: () => () => string; getPop: () => () => number | boolean | undefined; getPush: () => (...items: (number | boolean)[]) => number; getJoin: () => (separator?: string | undefined) => string; getReverse: () => () => (number | boolean)[]; getShift: () => () => number | boolean | undefined; getSort: () => (compareFn?: ((a: number | boolean, b: number | boolean) => number) | undefined) => [number, boolean]; getSplice: () => { (start: number, deleteCount?: number | undefined): (number | boolean)[]; (start: number, deleteCount: number, ...items: (number | boolean)[]): (number | boolean)[]; }; getUnshift: () => (...items: (number | boolean)[]) => number; getEvery: () => { <S extends number | boolean>(predicate: (value: number | boolean, index: number, array: (number | boolean)[]) => value is S, thisArg?: any): this is S[]; (predicate: (value: number | boolean, index: number, array: (number | boolean)[]) => unknown, thisArg?: any): boolean; }; getSome: () => (predicate: (value: number | boolean, index: number, array: (number | boolean)[]) => unknown, thisArg?: any) => boolean; getForEach: () => (callbackfn: (value: number | boolean, index: number, array: (number | boolean)[]) => void, thisArg?: any) => void; getMap: () => <U>(callbackfn: (value: number | boolean, index: number, array: (number | boolean)[]) => U, thisArg?: any) => U[]; getFilter: () => { <S extends number | boolean>(predicate: (value: number | boolean, index: number, array: (number | boolean)[]) => value is S, thisArg?: any): S[]; (predicate: (value: number | boolean, index: number, array: (number | boolean)[]) => unknown, thisArg?: any): (number | boolean)[]; }; getReduce: () => { (callbackfn: (previousValue: number | boolean, currentValue: number | boolean, currentIndex: number, array: (number | boolean)[]) => number | boolean): number | boolean; (callbackfn: (previousValue: number | boolean, currentValue: number | boolean, currentIndex: number, array: (number | boolean)[]) => number | boolean, initialValue: number | boolean): number | boolean; <U>(callbackfn: (previousValue: U, currentValue: number | boolean, currentIndex: number, array: (number | boolean)[]) => U, initialValue: U): U; }; getReduceRight: () => { (callbackfn: (previousValue: number | boolean, currentValue: number | boolean, currentIndex: number, array: (number | boolean)[]) => number | boolean): number | boolean; (callbackfn: (previousValue: number | boolean, currentValue: number | boolean, currentIndex: number, array: (number | boolean)[]) => number | boolean, initialValue: number | boolean): number | boolean; <U>(callbackfn: (previousValue: U, currentValue: number | boolean, currentIndex: number, array: (number | boolean)[]) => U, initialValue: U): U; }; get0: () => number; get1: () => boolean; }
4242

4343
// Filtering using 'as N' clause
4444

tests/cases/conformance/types/typeRelationships/assignmentCompatibility/intersectionIncludingPropFromGlobalAugmentation.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,3 +7,7 @@ interface Test1 { toString: null | 'string'; }
77
type Test2 = Test1 & { optional?: unknown };
88
declare const source: Test1;
99
const target: Test2 = { ...source };
10+
11+
const toString = target.toString;
12+
13+
export {}

0 commit comments

Comments
 (0)