diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 2fbdccba85bbf..bdfa33e4277e2 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -21491,7 +21491,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { eachTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive), intersectionState); } if (target.flags & TypeFlags.Union) { - return typeRelatedToSomeType(getRegularTypeOfObjectLiteral(source), target as UnionType, reportErrors && !(source.flags & TypeFlags.Primitive) && !(target.flags & TypeFlags.Primitive)); + return typeRelatedToSomeType(getRegularTypeOfObjectLiteral(source), target as UnionType, reportErrors && !(source.flags & TypeFlags.Primitive) && !(target.flags & TypeFlags.Primitive), intersectionState); } if (target.flags & TypeFlags.Intersection) { return typeRelatedToEachType(source, target as IntersectionType, reportErrors, IntersectionState.Target); @@ -21525,7 +21525,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { let result = Ternary.True; const sourceTypes = source.types; for (const sourceType of sourceTypes) { - const related = typeRelatedToSomeType(sourceType, target, /*reportErrors*/ false); + const related = typeRelatedToSomeType(sourceType, target, /*reportErrors*/ false, IntersectionState.None); if (!related) { return Ternary.False; } @@ -21534,7 +21534,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { return result; } - function typeRelatedToSomeType(source: Type, target: UnionOrIntersectionType, reportErrors: boolean): Ternary { + function typeRelatedToSomeType(source: Type, target: UnionOrIntersectionType, reportErrors: boolean, intersectionState: IntersectionState): Ternary { const targetTypes = target.types; if (target.flags & TypeFlags.Union) { if (containsType(targetTypes, source)) { @@ -21561,14 +21561,14 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { } const match = getMatchingUnionConstituentForType(target as UnionType, source); if (match) { - const related = isRelatedTo(source, match, RecursionFlags.Target, /*reportErrors*/ false); + const related = isRelatedTo(source, match, RecursionFlags.Target, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState); if (related) { return related; } } } for (const type of targetTypes) { - const related = isRelatedTo(source, type, RecursionFlags.Target, /*reportErrors*/ false); + const related = isRelatedTo(source, type, RecursionFlags.Target, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState); if (related) { return related; } @@ -21577,7 +21577,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // Elaborate only if we can find a best matching type in the target union const bestMatchingType = getBestMatchingType(source, target, isRelatedTo); if (bestMatchingType) { - isRelatedTo(source, bestMatchingType, RecursionFlags.Target, /*reportErrors*/ true); + isRelatedTo(source, bestMatchingType, RecursionFlags.Target, /*reportErrors*/ true, /*headMessage*/ undefined, intersectionState); } } return Ternary.False; diff --git a/tests/baselines/reference/nestedExcessPropertyChecking.errors.txt b/tests/baselines/reference/nestedExcessPropertyChecking.errors.txt index 393c2d1e35b0e..7c131d020aa34 100644 --- a/tests/baselines/reference/nestedExcessPropertyChecking.errors.txt +++ b/tests/baselines/reference/nestedExcessPropertyChecking.errors.txt @@ -88,4 +88,29 @@ nestedExcessPropertyChecking.ts(40,9): error TS2559: Type 'false' has no propert }, }, }; + + // Repro from #53412 + + type BaseItem = { + id: number; + } + type ExtendedItem = BaseItem & { + description: string | null + }; + + type BaseValue = { + // there are other fields + items: BaseItem[]; + } + type ExtendedValue = BaseValue & { + // there are other fields + items: ExtendedItem[]; + } + + const TEST_VALUE: ExtendedValue = { + items: [ + {id: 1, description: null}, + {id: 2, description: 'wigglytubble'}, + ] + }; \ No newline at end of file diff --git a/tests/baselines/reference/nestedExcessPropertyChecking.js b/tests/baselines/reference/nestedExcessPropertyChecking.js index 9d37f3d75425f..bd52494fc3d7c 100644 --- a/tests/baselines/reference/nestedExcessPropertyChecking.js +++ b/tests/baselines/reference/nestedExcessPropertyChecking.js @@ -64,6 +64,31 @@ const response: Query = { }, }, }; + +// Repro from #53412 + +type BaseItem = { + id: number; +} +type ExtendedItem = BaseItem & { + description: string | null +}; + +type BaseValue = { + // there are other fields + items: BaseItem[]; +} +type ExtendedValue = BaseValue & { + // there are other fields + items: ExtendedItem[]; +} + +const TEST_VALUE: ExtendedValue = { + items: [ + {id: 1, description: null}, + {id: 2, description: 'wigglytubble'}, + ] +}; //// [nestedExcessPropertyChecking.js] @@ -90,3 +115,9 @@ var response = { }, }, }; +var TEST_VALUE = { + items: [ + { id: 1, description: null }, + { id: 2, description: 'wigglytubble' }, + ] +}; diff --git a/tests/baselines/reference/nestedExcessPropertyChecking.symbols b/tests/baselines/reference/nestedExcessPropertyChecking.symbols index dbd83126cc5e6..1700d41c45548 100644 --- a/tests/baselines/reference/nestedExcessPropertyChecking.symbols +++ b/tests/baselines/reference/nestedExcessPropertyChecking.symbols @@ -165,3 +165,56 @@ const response: Query = { }, }; +// Repro from #53412 + +type BaseItem = { +>BaseItem : Symbol(BaseItem, Decl(nestedExcessPropertyChecking.ts, 62, 2)) + + id: number; +>id : Symbol(id, Decl(nestedExcessPropertyChecking.ts, 66, 17)) +} +type ExtendedItem = BaseItem & { +>ExtendedItem : Symbol(ExtendedItem, Decl(nestedExcessPropertyChecking.ts, 68, 1)) +>BaseItem : Symbol(BaseItem, Decl(nestedExcessPropertyChecking.ts, 62, 2)) + + description: string | null +>description : Symbol(description, Decl(nestedExcessPropertyChecking.ts, 69, 32)) + +}; + +type BaseValue = { +>BaseValue : Symbol(BaseValue, Decl(nestedExcessPropertyChecking.ts, 71, 2)) + + // there are other fields + items: BaseItem[]; +>items : Symbol(items, Decl(nestedExcessPropertyChecking.ts, 73, 18)) +>BaseItem : Symbol(BaseItem, Decl(nestedExcessPropertyChecking.ts, 62, 2)) +} +type ExtendedValue = BaseValue & { +>ExtendedValue : Symbol(ExtendedValue, Decl(nestedExcessPropertyChecking.ts, 76, 1)) +>BaseValue : Symbol(BaseValue, Decl(nestedExcessPropertyChecking.ts, 71, 2)) + + // there are other fields + items: ExtendedItem[]; +>items : Symbol(items, Decl(nestedExcessPropertyChecking.ts, 77, 34)) +>ExtendedItem : Symbol(ExtendedItem, Decl(nestedExcessPropertyChecking.ts, 68, 1)) +} + +const TEST_VALUE: ExtendedValue = { +>TEST_VALUE : Symbol(TEST_VALUE, Decl(nestedExcessPropertyChecking.ts, 82, 5)) +>ExtendedValue : Symbol(ExtendedValue, Decl(nestedExcessPropertyChecking.ts, 76, 1)) + + items: [ +>items : Symbol(items, Decl(nestedExcessPropertyChecking.ts, 82, 35)) + + {id: 1, description: null}, +>id : Symbol(id, Decl(nestedExcessPropertyChecking.ts, 84, 9)) +>description : Symbol(description, Decl(nestedExcessPropertyChecking.ts, 84, 15)) + + {id: 2, description: 'wigglytubble'}, +>id : Symbol(id, Decl(nestedExcessPropertyChecking.ts, 85, 9)) +>description : Symbol(description, Decl(nestedExcessPropertyChecking.ts, 85, 15)) + + ] +}; + diff --git a/tests/baselines/reference/nestedExcessPropertyChecking.types b/tests/baselines/reference/nestedExcessPropertyChecking.types index abed36ba6fa06..f5f74489d2259 100644 --- a/tests/baselines/reference/nestedExcessPropertyChecking.types +++ b/tests/baselines/reference/nestedExcessPropertyChecking.types @@ -160,3 +160,58 @@ const response: Query = { }, }; +// Repro from #53412 + +type BaseItem = { +>BaseItem : { id: number; } + + id: number; +>id : number +} +type ExtendedItem = BaseItem & { +>ExtendedItem : BaseItem & { description: string | null; } + + description: string | null +>description : string | null + +}; + +type BaseValue = { +>BaseValue : { items: BaseItem[]; } + + // there are other fields + items: BaseItem[]; +>items : BaseItem[] +} +type ExtendedValue = BaseValue & { +>ExtendedValue : BaseValue & { items: ExtendedItem[]; } + + // there are other fields + items: ExtendedItem[]; +>items : ExtendedItem[] +} + +const TEST_VALUE: ExtendedValue = { +>TEST_VALUE : ExtendedValue +>{ items: [ {id: 1, description: null}, {id: 2, description: 'wigglytubble'}, ]} : { items: ({ id: number; description: null; } | { id: number; description: string; })[]; } + + items: [ +>items : ({ id: number; description: null; } | { id: number; description: string; })[] +>[ {id: 1, description: null}, {id: 2, description: 'wigglytubble'}, ] : ({ id: number; description: null; } | { id: number; description: string; })[] + + {id: 1, description: null}, +>{id: 1, description: null} : { id: number; description: null; } +>id : number +>1 : 1 +>description : null + + {id: 2, description: 'wigglytubble'}, +>{id: 2, description: 'wigglytubble'} : { id: number; description: string; } +>id : number +>2 : 2 +>description : string +>'wigglytubble' : "wigglytubble" + + ] +}; + diff --git a/tests/cases/compiler/nestedExcessPropertyChecking.ts b/tests/cases/compiler/nestedExcessPropertyChecking.ts index 9e7c808b5e0ec..35caf37d7d13c 100644 --- a/tests/cases/compiler/nestedExcessPropertyChecking.ts +++ b/tests/cases/compiler/nestedExcessPropertyChecking.ts @@ -63,3 +63,28 @@ const response: Query = { }, }, }; + +// Repro from #53412 + +type BaseItem = { + id: number; +} +type ExtendedItem = BaseItem & { + description: string | null +}; + +type BaseValue = { + // there are other fields + items: BaseItem[]; +} +type ExtendedValue = BaseValue & { + // there are other fields + items: ExtendedItem[]; +} + +const TEST_VALUE: ExtendedValue = { + items: [ + {id: 1, description: null}, + {id: 2, description: 'wigglytubble'}, + ] +};