@@ -183,6 +183,7 @@ import {
183183 findAncestor,
184184 findBestPatternMatch,
185185 findIndex,
186+ findIterator,
186187 findLast,
187188 findLastIndex,
188189 findUseStrictPrologue,
@@ -948,6 +949,7 @@ import {
948949 skipTrivia,
949950 skipTypeChecking,
950951 some,
952+ someIterator,
951953 SourceFile,
952954 SpreadAssignment,
953955 SpreadElement,
@@ -13466,25 +13468,53 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1346613468
1346713469 function getPropertiesOfUnionOrIntersectionType(type: UnionOrIntersectionType): Symbol[] {
1346813470 if (!type.resolvedProperties) {
13469- const members = createSymbolTable();
13470- for (const current of type.types) {
13471- for (const prop of getPropertiesOfType(current)) {
13472- if (!members.has(prop.escapedName)) {
13473- const combinedProp = getPropertyOfUnionOrIntersectionType(type, prop.escapedName);
13474- if (combinedProp) {
13475- members.set(prop.escapedName, combinedProp);
13471+ for (const _ of iteratePropertiesOfUnionOrIntersectionType(type, /*skipYield*/ true)) {
13472+ Debug.fail("Iterator should have been empty.");
13473+ }
13474+ }
13475+ return type.resolvedProperties;
13476+ }
13477+
13478+ function *iteratePropertiesOfUnionOrIntersectionType(type: UnionOrIntersectionType, skipYield = false) {
13479+ if (type.resolvedProperties) {
13480+ if (!skipYield) {
13481+ yield* type.resolvedProperties;
13482+ }
13483+ return;
13484+ }
13485+
13486+ if (type.partiallyResolvedProperties) {
13487+ if (!skipYield) {
13488+ yield* type.partiallyResolvedProperties;
13489+ }
13490+ }
13491+
13492+ const seenSymbols = type.partiallyResolvedPropertiesSeenSymbols ??= createSymbolTable();
13493+ for (const current of type.types) {
13494+ for (const prop of getPropertiesOfType(current)) {
13495+ if (!seenSymbols.has(prop.escapedName)) {
13496+ const combinedProp = getPropertyOfUnionOrIntersectionType(type, prop.escapedName);
13497+ if (combinedProp) {
13498+ seenSymbols.set(prop.escapedName, combinedProp);
13499+ if (isNamedMember(combinedProp, prop.escapedName)) {
13500+ type.partiallyResolvedProperties = append(type.partiallyResolvedProperties, combinedProp);
13501+ if (!skipYield) {
13502+ yield combinedProp;
13503+ }
1347613504 }
1347713505 }
1347813506 }
13479- // The properties of a union type are those that are present in all constituent types, so
13480- // we only need to check the properties of the first type without index signature
13481- if (type.flags & TypeFlags.Union && getIndexInfosOfType(current).length === 0) {
13482- break;
13483- }
1348413507 }
13485- type.resolvedProperties = getNamedMembers(members);
13508+ // The properties of a union type are those that are present in all constituent types, so
13509+ // we only need to check the properties of the first type without index signature
13510+ if (type.flags & TypeFlags.Union && getIndexInfosOfType(current).length === 0) {
13511+ break;
13512+ }
1348613513 }
13487- return type.resolvedProperties;
13514+
13515+ type.resolvedProperties = type.partiallyResolvedProperties ?? emptyArray;
13516+ type.partiallyResolvedProperties = undefined;
13517+ type.partiallyResolvedPropertiesSeenSymbols = undefined;
1348813518 }
1348913519
1349013520 function getPropertiesOfType(type: Type): Symbol[] {
@@ -14136,7 +14166,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1413614166 else if (type.flags & TypeFlags.Intersection) {
1413714167 if (!((type as IntersectionType).objectFlags & ObjectFlags.IsNeverIntersectionComputed)) {
1413814168 (type as IntersectionType).objectFlags |= ObjectFlags.IsNeverIntersectionComputed |
14139- (some(getPropertiesOfUnionOrIntersectionType (type as IntersectionType), isNeverReducedProperty) ? ObjectFlags.IsNeverIntersection : 0);
14169+ (someIterator(iteratePropertiesOfUnionOrIntersectionType (type as IntersectionType), isNeverReducedProperty) ? ObjectFlags.IsNeverIntersection : 0);
1414014170 }
1414114171 return (type as IntersectionType).objectFlags & ObjectFlags.IsNeverIntersection ? neverType : type;
1414214172 }
@@ -14191,12 +14221,12 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
1419114221
1419214222 function elaborateNeverIntersection(errorInfo: DiagnosticMessageChain | undefined, type: Type) {
1419314223 if (type.flags & TypeFlags.Intersection && getObjectFlags(type) & ObjectFlags.IsNeverIntersection) {
14194- const neverProp = find(getPropertiesOfUnionOrIntersectionType (type as IntersectionType), isDiscriminantWithNeverType);
14224+ const neverProp = findIterator(iteratePropertiesOfUnionOrIntersectionType (type as IntersectionType), isDiscriminantWithNeverType);
1419514225 if (neverProp) {
1419614226 return chainDiagnosticMessages(errorInfo, Diagnostics.The_intersection_0_was_reduced_to_never_because_property_1_has_conflicting_types_in_some_constituents,
1419714227 typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.NoTypeReduction), symbolToString(neverProp));
1419814228 }
14199- const privateProp = find(getPropertiesOfUnionOrIntersectionType (type as IntersectionType), isConflictingPrivateProperty);
14229+ const privateProp = findIterator(iteratePropertiesOfUnionOrIntersectionType (type as IntersectionType), isConflictingPrivateProperty);
1420014230 if (privateProp) {
1420114231 return chainDiagnosticMessages(errorInfo, Diagnostics.The_intersection_0_was_reduced_to_never_because_property_1_exists_in_multiple_constituents_and_is_private_in_some,
1420214232 typeToString(type, /*enclosingDeclaration*/ undefined, TypeFormatFlags.NoTypeReduction), symbolToString(privateProp));
@@ -22372,7 +22402,7 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2237222402 function membersRelatedToIndexInfo(source: Type, targetInfo: IndexInfo, reportErrors: boolean, intersectionState: IntersectionState): Ternary {
2237322403 let result = Ternary.True;
2237422404 const keyType = targetInfo.keyType;
22375- const props = source.flags & TypeFlags.Intersection ? getPropertiesOfUnionOrIntersectionType (source as IntersectionType) : getPropertiesOfObjectType(source);
22405+ const props = source.flags & TypeFlags.Intersection ? iteratePropertiesOfUnionOrIntersectionType (source as IntersectionType) : getPropertiesOfObjectType(source);
2237622406 for (const prop of props) {
2237722407 // Skip over ignored JSX and symbol-named members
2237822408 if (isIgnoredJsxProperty(source, prop)) {
0 commit comments