diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index d94e86969c21a..191ccef571d22 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14900,8 +14900,9 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { // these partial properties when identifying discriminant properties, but otherwise they are filtered out // and do not appear to be present in the union type. function getUnionOrIntersectionProperty(type: UnionOrIntersectionType, name: __String, skipObjectFunctionPropertyAugment?: boolean): Symbol | undefined { - let property = type.propertyCacheWithoutObjectFunctionPropertyAugment?.get(name) || - !skipObjectFunctionPropertyAugment ? type.propertyCache?.get(name) : undefined; + let property = skipObjectFunctionPropertyAugment ? + type.propertyCacheWithoutObjectFunctionPropertyAugment?.get(name) : + type.propertyCache?.get(name); if (!property) { property = createUnionOrIntersectionProperty(type, name, skipObjectFunctionPropertyAugment); if (property) { @@ -14909,7 +14910,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { type.propertyCacheWithoutObjectFunctionPropertyAugment ||= createSymbolTable() : type.propertyCache ||= createSymbolTable(); properties.set(name, property); - if (skipObjectFunctionPropertyAugment && !type.propertyCache?.get(name)) { + // Propagate an entry from the non-augmented cache to the augmented cache unless the property is partial. + if (skipObjectFunctionPropertyAugment && !(getCheckFlags(property) & CheckFlags.Partial) && !type.propertyCache?.get(name)) { const properties = type.propertyCache ||= createSymbolTable(); properties.set(name, property); } diff --git a/tests/baselines/reference/checkJsxChildrenCanBeTupleType.types b/tests/baselines/reference/checkJsxChildrenCanBeTupleType.types index 33b0799bea5f0..1a88e30d0d9ea 100644 --- a/tests/baselines/reference/checkJsxChildrenCanBeTupleType.types +++ b/tests/baselines/reference/checkJsxChildrenCanBeTupleType.types @@ -4,7 +4,7 @@ Assignability cache: 2,200 / 2,200 (nearest 100) Type Count: 7,800 / 7,800 (nearest 100) Instantiation count: 90,000 / 90,000 (nearest 500) -Symbol count: 66,500 / 66,500 (nearest 500) +Symbol count: 67,000 / 67,000 (nearest 500) === checkJsxChildrenCanBeTupleType.tsx === /// diff --git a/tests/baselines/reference/infiniteConstraints.types b/tests/baselines/reference/infiniteConstraints.types index e5d0d49934694..4f954f2defa64 100644 --- a/tests/baselines/reference/infiniteConstraints.types +++ b/tests/baselines/reference/infiniteConstraints.types @@ -4,7 +4,7 @@ Assignability cache: 200 / 200 (nearest 100) Type Count: 1,000 / 1,000 (nearest 100) Instantiation count: 2,500 / 2,500 (nearest 500) -Symbol count: 25,500 / 26,000 (nearest 500) +Symbol count: 25,500 / 25,500 (nearest 500) === infiniteConstraints.ts === // Both of the following types trigger the recursion limiter in getImmediateBaseConstraint diff --git a/tests/baselines/reference/styledComponentsInstantiaionLimitNotReached.types b/tests/baselines/reference/styledComponentsInstantiaionLimitNotReached.types index 649098dd0bad5..2d8a8b33ae624 100644 --- a/tests/baselines/reference/styledComponentsInstantiaionLimitNotReached.types +++ b/tests/baselines/reference/styledComponentsInstantiaionLimitNotReached.types @@ -3,7 +3,7 @@ === Performance Stats === Identity cache: 200 / 200 (nearest 100) Assignability cache: 13,300 / 13,500 (nearest 100) -Type Count: 27,300 / 27,600 (nearest 100) +Type Count: 27,200 / 27,600 (nearest 100) Instantiation count: 374,500 / 375,500 (nearest 500) Symbol count: 92,000 / 92,000 (nearest 500) diff --git a/tests/baselines/reference/tsxReactEmitSpreadAttribute(target=esnext).types b/tests/baselines/reference/tsxReactEmitSpreadAttribute(target=esnext).types index 3cacbcf3f6193..d713485d6163b 100644 --- a/tests/baselines/reference/tsxReactEmitSpreadAttribute(target=esnext).types +++ b/tests/baselines/reference/tsxReactEmitSpreadAttribute(target=esnext).types @@ -4,7 +4,7 @@ Assignability cache: 2,200 / 2,300 (nearest 100) Type Count: 6,900 / 7,000 (nearest 100) Instantiation count: 73,000 / 73,500 (nearest 500) -Symbol count: 70,500 / 70,500 (nearest 500) +Symbol count: 70,500 / 71,000 (nearest 500) === test.tsx === /// diff --git a/tests/cases/fourslash/partialUnionPropertyCacheInconsistentErrors.ts b/tests/cases/fourslash/partialUnionPropertyCacheInconsistentErrors.ts new file mode 100644 index 0000000000000..7d793b520fa05 --- /dev/null +++ b/tests/cases/fourslash/partialUnionPropertyCacheInconsistentErrors.ts @@ -0,0 +1,45 @@ +/// + +// @strict: true +// @lib: esnext + +//// interface ComponentOptions { +//// setup?: (props: Props) => void; +//// name?: string; +//// } +//// +//// interface FunctionalComponent { +//// (props: P): void; +//// } +//// +//// type ConcreteComponent = +//// | ComponentOptions +//// | FunctionalComponent; +//// +//// type Component = ConcreteComponent; +//// +//// type WithInstallPlugin = { _prefix?: string }; +//// +//// +//// /**/ +//// export function withInstall( +//// component: C | C[], +//// target?: T, +//// ): string { +//// const componentWithInstall = (target ?? component) as T; +//// const components = Array.isArray(component) ? component : [component]; +//// +//// const { name } = components[0]; +//// if (name) { +//// return name; +//// } +//// +//// return ""; +//// } + +verify.noErrors(); + +goTo.marker(); +edit.insert("type C = Component['name']"); + +verify.noErrors(); \ No newline at end of file
{ +//// (props: P): void; +//// } +//// +//// type ConcreteComponent = +//// | ComponentOptions +//// | FunctionalComponent; +//// +//// type Component = ConcreteComponent; +//// +//// type WithInstallPlugin = { _prefix?: string }; +//// +//// +//// /**/ +//// export function withInstall( +//// component: C | C[], +//// target?: T, +//// ): string { +//// const componentWithInstall = (target ?? component) as T; +//// const components = Array.isArray(component) ? component : [component]; +//// +//// const { name } = components[0]; +//// if (name) { +//// return name; +//// } +//// +//// return ""; +//// } + +verify.noErrors(); + +goTo.marker(); +edit.insert("type C = Component['name']"); + +verify.noErrors(); \ No newline at end of file