@@ -14485,17 +14485,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1448514485 return getAugmentedPropertiesOfType(unionType);
1448614486 }
1448714487
14488+ const props = getMembersOfUnionOrIntersection(unionType as UnionType);
14489+ return arrayFrom(props.values());
14490+ }
14491+
14492+ function getMembersOfUnionOrIntersection(type: UnionOrIntersectionType): SymbolTable {
1448814493 const props = createSymbolTable();
14489- for (const memberType of types) {
14494+ for (const memberType of type. types) {
1449014495 for (const { escapedName } of getAugmentedPropertiesOfType(memberType)) {
1449114496 if (!props.has(escapedName)) {
14492- const prop = createUnionOrIntersectionProperty(unionType as UnionType , escapedName);
14497+ const prop = createUnionOrIntersectionProperty(type , escapedName);
1449314498 // May be undefined if the property is private
1449414499 if (prop) props.set(escapedName, prop);
1449514500 }
1449614501 }
1449714502 }
14498- return arrayFrom( props.values()) ;
14503+ return props;
1449914504 }
1450014505
1450114506 function getConstraintOfType(type: InstantiableType | UnionOrIntersectionType): Type | undefined {
@@ -21730,6 +21735,22 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2173021735 hasSubstitution ||= isNarrowingSubstitutionType(t); // This avoids displaying error messages with types like `T & T` when narrowing a return type
2173121736 if (hasInstantiable && hasNullableOrEmpty || hasSubstitution) return true;
2173221737 }
21738+
21739+ return false;
21740+ }
21741+
21742+ function isTypeMergeableIntersectionConstituent(type: Type) {
21743+ if (
21744+ type.flags === TypeFlags.Object &&
21745+ !!((type as ObjectType).objectFlags & ObjectFlags.Anonymous) &&
21746+ !((type as ObjectType).objectFlags & ObjectFlags.Instantiated)
21747+ ) {
21748+ if ((type as ObjectType).objectFlags & ObjectFlags.ReverseMapped) {
21749+ return isTypeMergeableIntersectionConstituent((type as ReverseMappedType).source);
21750+ }
21751+
21752+ return !typeHasCallOrConstructSignatures(type) && getIndexInfosOfType(type).length === 0;
21753+ }
2173321754 return false;
2173421755 }
2173521756
@@ -22151,12 +22172,19 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2215122172 // turn deferred type references into regular type references, simplify indexed access and
2215222173 // conditional types, and resolve substitution types to either the substitution (on the source
2215322174 // side) or the type variable (on the target side).
22154- const source = getNormalizedType(originalSource, /*writing*/ false);
22175+ let source = getNormalizedType(originalSource, /*writing*/ false);
2215522176 let target = getNormalizedType(originalTarget, /*writing*/ true);
2215622177
2215722178 if (source === target) return Ternary.True;
2215822179
2215922180 if (relation === identityRelation) {
22181+ if (source.flags & TypeFlags.Intersection) {
22182+ source = mergeIntersectionTypeIfPossible(source as IntersectionType, /*writing*/ false);
22183+ }
22184+ if (target.flags & TypeFlags.Intersection) {
22185+ target = mergeIntersectionTypeIfPossible(target as IntersectionType, /*writing*/ true);
22186+ }
22187+
2216022188 if (source.flags !== target.flags) return Ternary.False;
2216122189 if (source.flags & TypeFlags.Singleton) return Ternary.True;
2216222190 traceUnionsOrIntersectionsTooLarge(source, target);
@@ -22244,6 +22272,21 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2224422272 return Ternary.False;
2224522273 }
2224622274
22275+ function mergeIntersectionTypeIfPossible(type: IntersectionType, writing: boolean) {
22276+ if (every(type.types, isTypeMergeableIntersectionConstituent)) {
22277+ const reduced = getReducedType(type);
22278+ if (reduced.flags & TypeFlags.Intersection) {
22279+ type = reduced as IntersectionType;
22280+ const members = getMembersOfUnionOrIntersection(type);
22281+ const intersection = createAnonymousType(/*symbol*/ undefined, members, emptyArray, emptyArray, emptyArray);
22282+ intersection.aliasSymbol = type.aliasSymbol;
22283+ intersection.aliasTypeArguments = type.aliasTypeArguments;
22284+ return getNormalizedType(intersection, writing)
22285+ }
22286+ }
22287+ return type;
22288+ }
22289+
2224722290 function reportErrorResults(originalSource: Type, originalTarget: Type, source: Type, target: Type, headMessage: DiagnosticMessage | undefined) {
2224822291 const sourceHasBase = !!getSingleBaseForNonAugmentingSubtype(originalSource);
2224922292 const targetHasBase = !!getSingleBaseForNonAugmentingSubtype(originalTarget);
0 commit comments