Skip to content

Commit

Permalink
Route property check through recursive type tracking logic
Browse files Browse the repository at this point in the history
  • Loading branch information
ahejlsberg committed Mar 26, 2020
1 parent b1fe1b2 commit 39c4b8f
Showing 1 changed file with 13 additions and 10 deletions.
23 changes: 13 additions & 10 deletions src/compiler/checker.ts
Original file line number Diff line number Diff line change
Expand Up @@ -195,7 +195,7 @@ namespace ts {
None = 0,
Source = 1 << 0,
Target = 1 << 1,
ExcessCheck = 1 << 2,
PropertyCheck = 1 << 2,
}

const enum MappedTypeModifiers {
Expand Down Expand Up @@ -15418,14 +15418,14 @@ namespace ts {
if (source.flags & TypeFlags.Union) {
result = relation === comparableRelation ?
someTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive), intersectionState) :
eachTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive), intersectionState & IntersectionState.ExcessCheck);
eachTypeRelatedToType(source as UnionType, target, reportErrors && !(source.flags & TypeFlags.Primitive), intersectionState);
}
else {
if (target.flags & TypeFlags.Union) {
result = typeRelatedToSomeType(getRegularTypeOfObjectLiteral(source), <UnionType>target, reportErrors && !(source.flags & TypeFlags.Primitive) && !(target.flags & TypeFlags.Primitive), intersectionState & IntersectionState.ExcessCheck);
result = typeRelatedToSomeType(getRegularTypeOfObjectLiteral(source), <UnionType>target, reportErrors && !(source.flags & TypeFlags.Primitive) && !(target.flags & TypeFlags.Primitive));
}
else if (target.flags & TypeFlags.Intersection) {
result = typeRelatedToEachType(getRegularTypeOfObjectLiteral(source), target as IntersectionType, reportErrors, intersectionState & IntersectionState.ExcessCheck | IntersectionState.Target);
result = typeRelatedToEachType(getRegularTypeOfObjectLiteral(source), target as IntersectionType, reportErrors, IntersectionState.Target);
}
else if (source.flags & TypeFlags.Intersection) {
// Check to see if any constituents of the intersection are immediately related to the target.
Expand Down Expand Up @@ -15485,10 +15485,10 @@ namespace ts {
// function foo<T extends object>(x: { a?: string }, y: T & { a: boolean }) {
// x = y; // Mismatched property in source intersection
// }
if (result && !(intersectionState & IntersectionState.ExcessCheck) && (
if (result && (
target.flags & TypeFlags.Intersection && (isPerformingExcessPropertyChecks || isPerformingCommonPropertyChecks) ||
isNonGenericObjectType(target) && source.flags & TypeFlags.Intersection && !some((<IntersectionType>source).types, t => !!(getObjectFlags(t) & ObjectFlags.NonInferrableType)))) {
result &= propertiesRelatedTo(source, target, reportErrors, /*excludedProperties*/ undefined, IntersectionState.ExcessCheck);
result &= recursiveTypeRelatedTo(source, target, reportErrors, IntersectionState.PropertyCheck);
}

if (!result && reportErrors) {
Expand Down Expand Up @@ -15639,7 +15639,7 @@ namespace ts {
let result = Ternary.True;
const sourceTypes = source.types;
for (const sourceType of sourceTypes) {
const related = typeRelatedToSomeType(sourceType, target, /*reportErrors*/ false, IntersectionState.None);
const related = typeRelatedToSomeType(sourceType, target, /*reportErrors*/ false);
if (!related) {
return Ternary.False;
}
Expand All @@ -15648,20 +15648,20 @@ namespace ts {
return result;
}

function typeRelatedToSomeType(source: Type, target: UnionOrIntersectionType, reportErrors: boolean, intersectionState: IntersectionState): Ternary {
function typeRelatedToSomeType(source: Type, target: UnionOrIntersectionType, reportErrors: boolean): Ternary {
const targetTypes = target.types;
if (target.flags & TypeFlags.Union && containsType(targetTypes, source)) {
return Ternary.True;
}
for (const type of targetTypes) {
const related = isRelatedTo(source, type, /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState);
const related = isRelatedTo(source, type, /*reportErrors*/ false);
if (related) {
return related;
}
}
if (reportErrors) {
const bestMatchingType = getBestMatchingType(source, target, isRelatedTo);
isRelatedTo(source, bestMatchingType || targetTypes[targetTypes.length - 1], /*reportErrors*/ true, /*headMessage*/ undefined, intersectionState);
isRelatedTo(source, bestMatchingType || targetTypes[targetTypes.length - 1], /*reportErrors*/ true);
}
return Ternary.False;
}
Expand Down Expand Up @@ -15854,6 +15854,9 @@ namespace ts {
}

function structuredTypeRelatedTo(source: Type, target: Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary {
if (intersectionState & IntersectionState.PropertyCheck) {
return propertiesRelatedTo(source, target, reportErrors, /*excludedProperties*/ undefined, IntersectionState.None);
}
const flags = source.flags & target.flags;
if (relation === identityRelation && !(flags & TypeFlags.Object)) {
if (flags & TypeFlags.Index) {
Expand Down

0 comments on commit 39c4b8f

Please sign in to comment.