diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index fd786799b8b4c..383566ab291c9 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6832,11 +6832,9 @@ namespace ts { } } else { - // First, if the constraint type is a type parameter, obtain the base constraint. Then, - // if the key type is a 'keyof X', obtain 'keyof C' where C is the base constraint of X. - // Finally, iterate over the constituents of the resulting iteration type. - const keyType = constraintType.flags & TypeFlags.InstantiableNonPrimitive ? getApparentType(constraintType) : constraintType; - const iterationType = keyType.flags & TypeFlags.Index ? getIndexType(getApparentType((keyType).type)) : keyType; + // If the key type is a 'keyof X', obtain 'keyof C' where C is the base constraint of X. + // Then iterate over the constituents of the key type. + const iterationType = constraintType.flags & TypeFlags.Index ? getIndexType(getApparentType((constraintType).type)) : constraintType; forEachType(iterationType, addMemberForKeyType); } setStructuredTypeMembers(type, members, emptyArray, emptyArray, stringIndexInfo, numberIndexInfo); diff --git a/tests/baselines/reference/mappedTypeErrors.errors.txt b/tests/baselines/reference/mappedTypeErrors.errors.txt index 6d78b229fa4e3..a59859875bddf 100644 --- a/tests/baselines/reference/mappedTypeErrors.errors.txt +++ b/tests/baselines/reference/mappedTypeErrors.errors.txt @@ -39,9 +39,11 @@ tests/cases/conformance/types/mapped/mappedTypeErrors.ts(130,39): error TS2322: tests/cases/conformance/types/mapped/mappedTypeErrors.ts(136,16): error TS2322: Type 'T' is not assignable to type 'string | number | symbol'. Type 'T' is not assignable to type 'symbol'. tests/cases/conformance/types/mapped/mappedTypeErrors.ts(136,21): error TS2536: Type 'P' cannot be used to index type 'T'. +tests/cases/conformance/types/mapped/mappedTypeErrors.ts(148,17): error TS2339: Property 'foo' does not exist on type 'Pick'. +tests/cases/conformance/types/mapped/mappedTypeErrors.ts(152,17): error TS2339: Property 'foo' does not exist on type 'Record'. -==== tests/cases/conformance/types/mapped/mappedTypeErrors.ts (25 errors) ==== +==== tests/cases/conformance/types/mapped/mappedTypeErrors.ts (27 errors) ==== interface Shape { name: string; width: number; @@ -256,4 +258,18 @@ tests/cases/conformance/types/mapped/mappedTypeErrors.ts(136,21): error TS2536: pf: {x: 7}, pt: {x: 7, y: false}, }; + + // Repro from #28170 + + function test1(obj: Pick) { + let x = obj.foo; // Error + ~~~ +!!! error TS2339: Property 'foo' does not exist on type 'Pick'. + } + + function test2(obj: Record) { + let x = obj.foo; // Error + ~~~ +!!! error TS2339: Property 'foo' does not exist on type 'Record'. + } \ No newline at end of file diff --git a/tests/baselines/reference/mappedTypeErrors.js b/tests/baselines/reference/mappedTypeErrors.js index bc73780a4787d..276aeb76a1d15 100644 --- a/tests/baselines/reference/mappedTypeErrors.js +++ b/tests/baselines/reference/mappedTypeErrors.js @@ -142,6 +142,16 @@ let f: Foo2 = { pf: {x: 7}, pt: {x: 7, y: false}, }; + +// Repro from #28170 + +function test1(obj: Pick) { + let x = obj.foo; // Error +} + +function test2(obj: Record) { + let x = obj.foo; // Error +} //// [mappedTypeErrors.js] @@ -222,6 +232,13 @@ var f = { pf: { x: 7 }, pt: { x: 7, y: false } }; +// Repro from #28170 +function test1(obj) { + var x = obj.foo; // Error +} +function test2(obj) { + var x = obj.foo; // Error +} //// [mappedTypeErrors.d.ts] @@ -300,3 +317,5 @@ declare type O = { }; declare let o: O; declare let f: Foo2; +declare function test1(obj: Pick): void; +declare function test2(obj: Record): void; diff --git a/tests/baselines/reference/mappedTypeErrors.symbols b/tests/baselines/reference/mappedTypeErrors.symbols index 80ce5d498459b..e2f3b57750606 100644 --- a/tests/baselines/reference/mappedTypeErrors.symbols +++ b/tests/baselines/reference/mappedTypeErrors.symbols @@ -540,3 +540,34 @@ let f: Foo2 = { }; +// Repro from #28170 + +function test1(obj: Pick) { +>test1 : Symbol(test1, Decl(mappedTypeErrors.ts, 142, 2)) +>T : Symbol(T, Decl(mappedTypeErrors.ts, 146, 15)) +>K : Symbol(K, Decl(mappedTypeErrors.ts, 146, 17)) +>T : Symbol(T, Decl(mappedTypeErrors.ts, 146, 15)) +>obj : Symbol(obj, Decl(mappedTypeErrors.ts, 146, 37)) +>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(mappedTypeErrors.ts, 146, 15)) +>K : Symbol(K, Decl(mappedTypeErrors.ts, 146, 17)) + + let x = obj.foo; // Error +>x : Symbol(x, Decl(mappedTypeErrors.ts, 147, 7)) +>obj : Symbol(obj, Decl(mappedTypeErrors.ts, 146, 37)) +} + +function test2(obj: Record) { +>test2 : Symbol(test2, Decl(mappedTypeErrors.ts, 148, 1)) +>T : Symbol(T, Decl(mappedTypeErrors.ts, 150, 15)) +>K : Symbol(K, Decl(mappedTypeErrors.ts, 150, 17)) +>T : Symbol(T, Decl(mappedTypeErrors.ts, 150, 15)) +>obj : Symbol(obj, Decl(mappedTypeErrors.ts, 150, 37)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>K : Symbol(K, Decl(mappedTypeErrors.ts, 150, 17)) + + let x = obj.foo; // Error +>x : Symbol(x, Decl(mappedTypeErrors.ts, 151, 7)) +>obj : Symbol(obj, Decl(mappedTypeErrors.ts, 150, 37)) +} + diff --git a/tests/baselines/reference/mappedTypeErrors.types b/tests/baselines/reference/mappedTypeErrors.types index c1ae739913798..cfa0df3cd586e 100644 --- a/tests/baselines/reference/mappedTypeErrors.types +++ b/tests/baselines/reference/mappedTypeErrors.types @@ -501,3 +501,27 @@ let f: Foo2 = { }; +// Repro from #28170 + +function test1(obj: Pick) { +>test1 : (obj: Pick) => void +>obj : Pick + + let x = obj.foo; // Error +>x : any +>obj.foo : any +>obj : Pick +>foo : any +} + +function test2(obj: Record) { +>test2 : (obj: Record) => void +>obj : Record + + let x = obj.foo; // Error +>x : any +>obj.foo : any +>obj : Record +>foo : any +} + diff --git a/tests/cases/conformance/types/mapped/mappedTypeErrors.ts b/tests/cases/conformance/types/mapped/mappedTypeErrors.ts index cec1fbf839554..a38979054ecff 100644 --- a/tests/cases/conformance/types/mapped/mappedTypeErrors.ts +++ b/tests/cases/conformance/types/mapped/mappedTypeErrors.ts @@ -144,3 +144,13 @@ let f: Foo2 = { pf: {x: 7}, pt: {x: 7, y: false}, }; + +// Repro from #28170 + +function test1(obj: Pick) { + let x = obj.foo; // Error +} + +function test2(obj: Record) { + let x = obj.foo; // Error +}