From 30d1ecd1bd022bd15390d6b102adc72954955279 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 26 Oct 2018 14:14:53 -0700 Subject: [PATCH 1/3] Constraint for { [P in K]: XXX } should be empty type --- src/compiler/checker.ts | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) 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); From 24e37452960358a592c8a7526fc3d2081f78f388 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 26 Oct 2018 15:32:10 -0700 Subject: [PATCH 2/3] Add regression test --- .../cases/conformance/types/mapped/mappedTypeErrors.ts | 10 ++++++++++ 1 file changed, 10 insertions(+) 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 +} From 00fbdedbccdb2daf10ee56ed0793ecc1d7a1d727 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Fri, 26 Oct 2018 15:32:18 -0700 Subject: [PATCH 3/3] Accept new baselines --- .../reference/mappedTypeErrors.errors.txt | 18 ++++++++++- tests/baselines/reference/mappedTypeErrors.js | 19 ++++++++++++ .../reference/mappedTypeErrors.symbols | 31 +++++++++++++++++++ .../reference/mappedTypeErrors.types | 24 ++++++++++++++ 4 files changed, 91 insertions(+), 1 deletion(-) 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 +} +