From 1b9d10fe81a9d5f8ab75978250a7661f89f85c40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=96=87=E7=92=90?= Date: Wed, 2 Jan 2019 17:15:02 +0800 Subject: [PATCH 1/3] try to link symbol for mapped object type --- src/compiler/checker.ts | 9 ++-- tests/baselines/reference/mappedTypes7.js | 23 +++++++++ .../baselines/reference/mappedTypes7.symbols | 48 +++++++++++++++++++ tests/baselines/reference/mappedTypes7.types | 38 +++++++++++++++ .../conformance/types/mapped/mappedTypes7.ts | 16 +++++++ 5 files changed, 130 insertions(+), 4 deletions(-) create mode 100644 tests/baselines/reference/mappedTypes7.js create mode 100644 tests/baselines/reference/mappedTypes7.symbols create mode 100644 tests/baselines/reference/mappedTypes7.types create mode 100644 tests/cases/conformance/types/mapped/mappedTypes7.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 23c5568f2e5f4..c332feb1515d0 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7141,10 +7141,11 @@ namespace ts { prop.type = strictNullChecks && isOptional && !isTypeAssignableTo(undefinedType, propType) ? getOptionalType(propType) : strictNullChecks && !isOptional && modifiersProp && modifiersProp.flags & SymbolFlags.Optional ? getTypeWithFacts(propType, TypeFacts.NEUndefined) : propType; - if (modifiersProp) { - prop.syntheticOrigin = modifiersProp; - prop.declarations = modifiersProp.declarations; - } + + const templateProp = (templateType.flags & TypeFlags.IndexedAccess) && getPropertyOfType((templateType).objectType, propName) + + prop.syntheticOrigin = templateProp || modifiersProp; + prop.declarations = templateProp && templateProp.declarations || modifiersProp && modifiersProp.declarations || undefined!; prop.nameType = t; members.set(propName, prop); } diff --git a/tests/baselines/reference/mappedTypes7.js b/tests/baselines/reference/mappedTypes7.js new file mode 100644 index 0000000000000..61fd828ef6db0 --- /dev/null +++ b/tests/baselines/reference/mappedTypes7.js @@ -0,0 +1,23 @@ +//// [mappedTypes7.ts] +interface I { + a: number; + b: number; +} +type J = { + [K in 'b' | 'a']: I[K] +}; + +type L = Pick + +declare const j: J; +j.a; +j.b; + +declare const l: L +l.a + + +//// [mappedTypes7.js] +j.a; +j.b; +l.a; diff --git a/tests/baselines/reference/mappedTypes7.symbols b/tests/baselines/reference/mappedTypes7.symbols new file mode 100644 index 0000000000000..2dd2f63b98798 --- /dev/null +++ b/tests/baselines/reference/mappedTypes7.symbols @@ -0,0 +1,48 @@ +=== tests/cases/conformance/types/mapped/mappedTypes7.ts === +interface I { +>I : Symbol(I, Decl(mappedTypes7.ts, 0, 0)) + + a: number; +>a : Symbol(I.a, Decl(mappedTypes7.ts, 0, 13)) + + b: number; +>b : Symbol(I.b, Decl(mappedTypes7.ts, 1, 14)) +} +type J = { +>J : Symbol(J, Decl(mappedTypes7.ts, 3, 1)) + + [K in 'b' | 'a']: I[K] +>K : Symbol(K, Decl(mappedTypes7.ts, 5, 5)) +>I : Symbol(I, Decl(mappedTypes7.ts, 0, 0)) +>K : Symbol(K, Decl(mappedTypes7.ts, 5, 5)) + +}; + +type L = Pick +>L : Symbol(L, Decl(mappedTypes7.ts, 6, 2)) +>Pick : Symbol(Pick, Decl(lib.es5.d.ts, --, --)) +>J : Symbol(J, Decl(mappedTypes7.ts, 3, 1)) + +declare const j: J; +>j : Symbol(j, Decl(mappedTypes7.ts, 10, 13)) +>J : Symbol(J, Decl(mappedTypes7.ts, 3, 1)) + +j.a; +>j.a : Symbol(a, Decl(mappedTypes7.ts, 0, 13)) +>j : Symbol(j, Decl(mappedTypes7.ts, 10, 13)) +>a : Symbol(a, Decl(mappedTypes7.ts, 0, 13)) + +j.b; +>j.b : Symbol(b, Decl(mappedTypes7.ts, 1, 14)) +>j : Symbol(j, Decl(mappedTypes7.ts, 10, 13)) +>b : Symbol(b, Decl(mappedTypes7.ts, 1, 14)) + +declare const l: L +>l : Symbol(l, Decl(mappedTypes7.ts, 14, 13)) +>L : Symbol(L, Decl(mappedTypes7.ts, 6, 2)) + +l.a +>l.a : Symbol(a, Decl(mappedTypes7.ts, 0, 13)) +>l : Symbol(l, Decl(mappedTypes7.ts, 14, 13)) +>a : Symbol(a, Decl(mappedTypes7.ts, 0, 13)) + diff --git a/tests/baselines/reference/mappedTypes7.types b/tests/baselines/reference/mappedTypes7.types new file mode 100644 index 0000000000000..36939a5bbc03d --- /dev/null +++ b/tests/baselines/reference/mappedTypes7.types @@ -0,0 +1,38 @@ +=== tests/cases/conformance/types/mapped/mappedTypes7.ts === +interface I { + a: number; +>a : number + + b: number; +>b : number +} +type J = { +>J : J + + [K in 'b' | 'a']: I[K] +}; + +type L = Pick +>L : Pick + +declare const j: J; +>j : J + +j.a; +>j.a : number +>j : J +>a : number + +j.b; +>j.b : number +>j : J +>b : number + +declare const l: L +>l : Pick + +l.a +>l.a : number +>l : Pick +>a : number + diff --git a/tests/cases/conformance/types/mapped/mappedTypes7.ts b/tests/cases/conformance/types/mapped/mappedTypes7.ts new file mode 100644 index 0000000000000..afadb532e22f2 --- /dev/null +++ b/tests/cases/conformance/types/mapped/mappedTypes7.ts @@ -0,0 +1,16 @@ +interface I { + a: number; + b: number; +} +type J = { + [K in 'b' | 'a']: I[K] +}; + +type L = Pick + +declare const j: J; +j.a; +j.b; + +declare const l: L +l.a From 09c400d6843ef9b9abc31876e37044cff9b441e6 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E7=8E=8B=E6=96=87=E7=92=90?= Date: Fri, 4 Jan 2019 10:46:50 +0800 Subject: [PATCH 2/3] fix lint --- src/compiler/checker.ts | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 77d5cabaf6ad2..79edcae052a3a 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -7169,10 +7169,9 @@ namespace ts { // type, we include 'undefined' in the type. Similarly, when creating a non-optional property in strictNullChecks // mode, if the underlying property is optional we remove 'undefined' from the type. prop.type = strictNullChecks && isOptional && !isTypeAssignableTo(undefinedType, propType) ? getOptionalType(propType) : - strictNullChecks && !isOptional && modifiersProp && modifiersProp.flags & SymbolFlags.Optional ? getTypeWithFacts(propType, TypeFacts.NEUndefined) : - propType; - - const templateProp = (templateType.flags & TypeFlags.IndexedAccess) && getPropertyOfType((templateType).objectType, propName) + strictNullChecks && !isOptional && modifiersProp && modifiersProp.flags & SymbolFlags.Optional ? getTypeWithFacts(propType, TypeFacts.NEUndefined) : propType; + + const templateProp = (templateType.flags & TypeFlags.IndexedAccess) && getPropertyOfType((templateType).objectType, propName); prop.syntheticOrigin = templateProp || modifiersProp; prop.declarations = templateProp && templateProp.declarations || modifiersProp && modifiersProp.declarations || undefined!; From d48807195cfa3e63d17a6e48510d56518f049b46 Mon Sep 17 00:00:00 2001 From: kingwl Date: Thu, 26 Mar 2020 23:42:27 +0800 Subject: [PATCH 3/3] Fix merge conflict --- src/compiler/checker.ts | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index e0672300f1cd4..7c1acce01f4b4 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -9656,6 +9656,7 @@ namespace ts { if (isTypeUsableAsPropertyName(t)) { const propName = getPropertyNameFromType(t); const modifiersProp = getPropertyOfType(modifiersType, propName); + const templateProp = (templateType.flags & TypeFlags.IndexedAccess) && getPropertyOfType((templateType).objectType, propName); const isOptional = !!(templateModifiers & MappedTypeModifiers.IncludeOptional || !(templateModifiers & MappedTypeModifiers.ExcludeOptional) && modifiersProp && modifiersProp.flags & SymbolFlags.Optional); const isReadonly = !!(templateModifiers & MappedTypeModifiers.IncludeReadonly || @@ -9663,12 +9664,12 @@ namespace ts { const stripOptional = strictNullChecks && !isOptional && modifiersProp && modifiersProp.flags & SymbolFlags.Optional; const prop = createSymbol(SymbolFlags.Property | (isOptional ? SymbolFlags.Optional : 0), propName, CheckFlags.Mapped | (isReadonly ? CheckFlags.Readonly : 0) | (stripOptional ? CheckFlags.StripOptional : 0)); + prop.mappedType = type; prop.mapper = templateMapper; - if (modifiersProp) { - prop.syntheticOrigin = modifiersProp; - prop.declarations = modifiersProp.declarations; - } + + prop.syntheticOrigin = templateProp || modifiersProp; + prop.declarations = templateProp && templateProp.declarations || modifiersProp && modifiersProp.declarations || undefined!; prop.nameType = t; members.set(propName, prop); }