From 247d2a0215ffd411cdebae624e398166dcdf6e03 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 24 May 2020 17:49:39 -0700 Subject: [PATCH 1/2] Fix relation between generic mapped type and type with index signature(s) --- src/compiler/checker.ts | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 32965372e83fc..0dbcf25dbae33 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -17288,9 +17288,10 @@ namespace ts { return Ternary.True; } if (isGenericMappedType(source)) { - // A generic mapped type { [P in K]: T } is related to an index signature { [x: string]: U } - // if T is related to U. - return kind === IndexKind.String ? isRelatedTo(getTemplateTypeFromMappedType(source), targetType, reportErrors) : Ternary.False; + // A generic mapped type { [P in K]: T } is related to a type with an index signature + // { [x: string]: U }, and optionally with an index signature { [x: number]: V }, + // if T is related to U and V. + return getIndexTypeOfType(target, IndexKind.String) ? isRelatedTo(getTemplateTypeFromMappedType(source), targetType, reportErrors) : Ternary.False; } const indexType = getIndexTypeOfType(source, kind) || kind === IndexKind.Number && getIndexTypeOfType(source, IndexKind.String); if (indexType) { From 4871c58642655d1234b71e362599023a692d5e88 Mon Sep 17 00:00:00 2001 From: Anders Hejlsberg Date: Sun, 24 May 2020 17:54:09 -0700 Subject: [PATCH 2/2] Add tests --- .../mappedTypeAndIndexSignatureRelation.js | 36 ++++++ ...appedTypeAndIndexSignatureRelation.symbols | 117 ++++++++++++++++++ .../mappedTypeAndIndexSignatureRelation.types | 51 ++++++++ .../mappedTypeAndIndexSignatureRelation.ts | 33 +++++ 4 files changed, 237 insertions(+) create mode 100644 tests/baselines/reference/mappedTypeAndIndexSignatureRelation.js create mode 100644 tests/baselines/reference/mappedTypeAndIndexSignatureRelation.symbols create mode 100644 tests/baselines/reference/mappedTypeAndIndexSignatureRelation.types create mode 100644 tests/cases/compiler/mappedTypeAndIndexSignatureRelation.ts diff --git a/tests/baselines/reference/mappedTypeAndIndexSignatureRelation.js b/tests/baselines/reference/mappedTypeAndIndexSignatureRelation.js new file mode 100644 index 0000000000000..cec41af2055fc --- /dev/null +++ b/tests/baselines/reference/mappedTypeAndIndexSignatureRelation.js @@ -0,0 +1,36 @@ +//// [mappedTypeAndIndexSignatureRelation.ts] +type Same = { [P in keyof T]: T[P] }; + +type T1> = T; +type T2> = T1>; + +// Repro from #38235 + +type Foo> = + IdentifierT +; + +type Bar, T> = + { + [k in keyof T] : Foo + } +; + +type Merge2 = { [k in keyof T] : T[k] } +type Bar2, T> = + { + [k in keyof T]: Foo> + } +; + +type Identity = T; +type Merge3 = Identity<{ [k in keyof T] : T[k] }> +type Bar3, T> = + { + [k in keyof T]: Foo> + } +; + + +//// [mappedTypeAndIndexSignatureRelation.js] +"use strict"; diff --git a/tests/baselines/reference/mappedTypeAndIndexSignatureRelation.symbols b/tests/baselines/reference/mappedTypeAndIndexSignatureRelation.symbols new file mode 100644 index 0000000000000..431507c8ad8d3 --- /dev/null +++ b/tests/baselines/reference/mappedTypeAndIndexSignatureRelation.symbols @@ -0,0 +1,117 @@ +=== tests/cases/compiler/mappedTypeAndIndexSignatureRelation.ts === +type Same = { [P in keyof T]: T[P] }; +>Same : Symbol(Same, Decl(mappedTypeAndIndexSignatureRelation.ts, 0, 0)) +>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 0, 10)) +>P : Symbol(P, Decl(mappedTypeAndIndexSignatureRelation.ts, 0, 18)) +>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 0, 10)) +>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 0, 10)) +>P : Symbol(P, Decl(mappedTypeAndIndexSignatureRelation.ts, 0, 18)) + +type T1> = T; +>T1 : Symbol(T1, Decl(mappedTypeAndIndexSignatureRelation.ts, 0, 40)) +>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 2, 8)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 2, 8)) + +type T2> = T1>; +>T2 : Symbol(T2, Decl(mappedTypeAndIndexSignatureRelation.ts, 2, 51)) +>U : Symbol(U, Decl(mappedTypeAndIndexSignatureRelation.ts, 3, 8)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --)) +>T1 : Symbol(T1, Decl(mappedTypeAndIndexSignatureRelation.ts, 0, 40)) +>Same : Symbol(Same, Decl(mappedTypeAndIndexSignatureRelation.ts, 0, 0)) +>U : Symbol(U, Decl(mappedTypeAndIndexSignatureRelation.ts, 3, 8)) + +// Repro from #38235 + +type Foo> = +>Foo : Symbol(Foo, Decl(mappedTypeAndIndexSignatureRelation.ts, 3, 61)) +>IdentifierT : Symbol(IdentifierT, Decl(mappedTypeAndIndexSignatureRelation.ts, 7, 9)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --)) +>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --)) + + IdentifierT +>IdentifierT : Symbol(IdentifierT, Decl(mappedTypeAndIndexSignatureRelation.ts, 7, 9)) + +; + +type Bar, T> = +>Bar : Symbol(Bar, Decl(mappedTypeAndIndexSignatureRelation.ts, 9, 1)) +>IdentifierT : Symbol(IdentifierT, Decl(mappedTypeAndIndexSignatureRelation.ts, 11, 9)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --)) +>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 11, 62)) + { + [k in keyof T] : Foo +>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 13, 9)) +>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 11, 62)) +>Foo : Symbol(Foo, Decl(mappedTypeAndIndexSignatureRelation.ts, 3, 61)) +>IdentifierT : Symbol(IdentifierT, Decl(mappedTypeAndIndexSignatureRelation.ts, 11, 9)) +>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 13, 44)) +>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 13, 9)) + } +; + +type Merge2 = { [k in keyof T] : T[k] } +>Merge2 : Symbol(Merge2, Decl(mappedTypeAndIndexSignatureRelation.ts, 15, 1)) +>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 17, 12)) +>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 17, 20)) +>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 17, 12)) +>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 17, 12)) +>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 17, 20)) + +type Bar2, T> = +>Bar2 : Symbol(Bar2, Decl(mappedTypeAndIndexSignatureRelation.ts, 17, 42)) +>IdentifierT : Symbol(IdentifierT, Decl(mappedTypeAndIndexSignatureRelation.ts, 18, 10)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --)) +>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 18, 63)) + { + [k in keyof T]: Foo> +>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 20, 9)) +>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 18, 63)) +>Foo : Symbol(Foo, Decl(mappedTypeAndIndexSignatureRelation.ts, 3, 61)) +>Merge2 : Symbol(Merge2, Decl(mappedTypeAndIndexSignatureRelation.ts, 15, 1)) +>IdentifierT : Symbol(IdentifierT, Decl(mappedTypeAndIndexSignatureRelation.ts, 18, 10)) +>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 20, 50)) +>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 20, 9)) + } +; + +type Identity = T; +>Identity : Symbol(Identity, Decl(mappedTypeAndIndexSignatureRelation.ts, 22, 1)) +>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 24, 14)) +>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 24, 14)) + +type Merge3 = Identity<{ [k in keyof T] : T[k] }> +>Merge3 : Symbol(Merge3, Decl(mappedTypeAndIndexSignatureRelation.ts, 24, 21)) +>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 25, 12)) +>Identity : Symbol(Identity, Decl(mappedTypeAndIndexSignatureRelation.ts, 22, 1)) +>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 25, 29)) +>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 25, 12)) +>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 25, 12)) +>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 25, 29)) + +type Bar3, T> = +>Bar3 : Symbol(Bar3, Decl(mappedTypeAndIndexSignatureRelation.ts, 25, 52)) +>IdentifierT : Symbol(IdentifierT, Decl(mappedTypeAndIndexSignatureRelation.ts, 26, 10)) +>Record : Symbol(Record, Decl(lib.es5.d.ts, --, --)) +>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --)) +>PropertyKey : Symbol(PropertyKey, Decl(lib.es5.d.ts, --, --)) +>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 26, 63)) + { + [k in keyof T]: Foo> +>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 28, 9)) +>T : Symbol(T, Decl(mappedTypeAndIndexSignatureRelation.ts, 26, 63)) +>Foo : Symbol(Foo, Decl(mappedTypeAndIndexSignatureRelation.ts, 3, 61)) +>Merge3 : Symbol(Merge3, Decl(mappedTypeAndIndexSignatureRelation.ts, 24, 21)) +>IdentifierT : Symbol(IdentifierT, Decl(mappedTypeAndIndexSignatureRelation.ts, 26, 10)) +>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 28, 50)) +>k : Symbol(k, Decl(mappedTypeAndIndexSignatureRelation.ts, 28, 9)) + } +; + diff --git a/tests/baselines/reference/mappedTypeAndIndexSignatureRelation.types b/tests/baselines/reference/mappedTypeAndIndexSignatureRelation.types new file mode 100644 index 0000000000000..895b0c728fc12 --- /dev/null +++ b/tests/baselines/reference/mappedTypeAndIndexSignatureRelation.types @@ -0,0 +1,51 @@ +=== tests/cases/compiler/mappedTypeAndIndexSignatureRelation.ts === +type Same = { [P in keyof T]: T[P] }; +>Same : Same + +type T1> = T; +>T1 : T + +type T2> = T1>; +>T2 : Same + +// Repro from #38235 + +type Foo> = +>Foo : IdentifierT + + IdentifierT +; + +type Bar, T> = +>Bar : Bar + { + [k in keyof T] : Foo +>k : k + } +; + +type Merge2 = { [k in keyof T] : T[k] } +>Merge2 : Merge2 + +type Bar2, T> = +>Bar2 : Bar2 + { + [k in keyof T]: Foo> +>k : k + } +; + +type Identity = T; +>Identity : T + +type Merge3 = Identity<{ [k in keyof T] : T[k] }> +>Merge3 : { [k in keyof T]: T[k]; } + +type Bar3, T> = +>Bar3 : Bar3 + { + [k in keyof T]: Foo> +>k : k + } +; + diff --git a/tests/cases/compiler/mappedTypeAndIndexSignatureRelation.ts b/tests/cases/compiler/mappedTypeAndIndexSignatureRelation.ts new file mode 100644 index 0000000000000..165e6e4b17b73 --- /dev/null +++ b/tests/cases/compiler/mappedTypeAndIndexSignatureRelation.ts @@ -0,0 +1,33 @@ +// @strict: true + +type Same = { [P in keyof T]: T[P] }; + +type T1> = T; +type T2> = T1>; + +// Repro from #38235 + +type Foo> = + IdentifierT +; + +type Bar, T> = + { + [k in keyof T] : Foo + } +; + +type Merge2 = { [k in keyof T] : T[k] } +type Bar2, T> = + { + [k in keyof T]: Foo> + } +; + +type Identity = T; +type Merge3 = Identity<{ [k in keyof T] : T[k] }> +type Bar3, T> = + { + [k in keyof T]: Foo> + } +;