diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index a2f791efbd0..df6cf8609a1 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -26122,12 +26122,12 @@ namespace ts { return !!(getCheckFlags(symbol) & CheckFlags.Mapped && !(symbol as MappedSymbol).type && findResolutionCycleStartIndex(symbol, TypeSystemPropertyName.Type) >= 0); } - function getTypeOfPropertyOfContextualType(type: Type, name: __String) { + function getTypeOfPropertyOfContextualType(type: Type, name: __String, nameType?: Type) { return mapType(type, t => { if (isGenericMappedType(t)) { const constraint = getConstraintTypeFromMappedType(t); const constraintOfConstraint = getBaseConstraintOfType(constraint) || constraint; - const propertyNameType = getStringLiteralType(unescapeLeadingUnderscores(name)); + const propertyNameType = nameType || getStringLiteralType(unescapeLeadingUnderscores(name)); if (isTypeAssignableTo(propertyNameType, constraintOfConstraint)) { return substituteIndexedMappedType(t, propertyNameType); } @@ -26143,7 +26143,7 @@ namespace ts { return restType; } } - return findApplicableIndexInfo(getIndexInfosOfStructuredType(t), getStringLiteralType(unescapeLeadingUnderscores(name)))?.type; + return findApplicableIndexInfo(getIndexInfosOfStructuredType(t), nameType || getStringLiteralType(unescapeLeadingUnderscores(name)))?.type; } return undefined; }, /*noReductions*/ true); @@ -26173,7 +26173,8 @@ namespace ts { // For a (non-symbol) computed property, there is no reason to look up the name // in the type. It will just be "__computed", which does not appear in any // SymbolTable. - return getTypeOfPropertyOfContextualType(type, getSymbolOfNode(element).escapedName); + const symbol = getSymbolOfNode(element); + return getTypeOfPropertyOfContextualType(type, symbol.escapedName, getSymbolLinks(symbol).nameType); } if (element.name) { const nameType = getLiteralTypeFromPropertyName(element.name); diff --git a/src/lib/es5.d.ts b/src/lib/es5.d.ts index b10358a0f7e..75cc242c231 100644 --- a/src/lib/es5.d.ts +++ b/src/lib/es5.d.ts @@ -96,7 +96,7 @@ interface PropertyDescriptor { } interface PropertyDescriptorMap { - [s: string]: PropertyDescriptor; + [key: PropertyKey]: PropertyDescriptor; } interface Object { diff --git a/tests/baselines/reference/contextuallyTypedSymbolNamedProperties.js b/tests/baselines/reference/contextuallyTypedSymbolNamedProperties.js new file mode 100644 index 00000000000..fc949d87312 --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedSymbolNamedProperties.js @@ -0,0 +1,53 @@ +//// [contextuallyTypedSymbolNamedProperties.ts] +// Repros from #43628 + +const A = Symbol("A"); +const B = Symbol("B"); + +type Action = + | {type: typeof A, data: string} + | {type: typeof B, data: number} + +declare const ab: Action; + +declare function f(action: T, blah: { [K in T['type']]: (p: K) => void }): any; + +f(ab, { + [A]: ap => { ap.description }, + [B]: bp => { bp.description }, +}) + +const x: { [sym: symbol]: (p: string) => void } = { [A]: s => s.length }; + + +//// [contextuallyTypedSymbolNamedProperties.js] +"use strict"; +// Repros from #43628 +const A = Symbol("A"); +const B = Symbol("B"); +f(ab, { + [A]: ap => { ap.description; }, + [B]: bp => { bp.description; }, +}); +const x = { [A]: s => s.length }; + + +//// [contextuallyTypedSymbolNamedProperties.d.ts] +declare const A: unique symbol; +declare const B: unique symbol; +declare type Action = { + type: typeof A; + data: string; +} | { + type: typeof B; + data: number; +}; +declare const ab: Action; +declare function f(action: T, blah: { + [K in T['type']]: (p: K) => void; +}): any; +declare const x: { + [sym: symbol]: (p: string) => void; +}; diff --git a/tests/baselines/reference/contextuallyTypedSymbolNamedProperties.symbols b/tests/baselines/reference/contextuallyTypedSymbolNamedProperties.symbols new file mode 100644 index 00000000000..0c186e59f61 --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedSymbolNamedProperties.symbols @@ -0,0 +1,73 @@ +=== tests/cases/compiler/contextuallyTypedSymbolNamedProperties.ts === +// Repros from #43628 + +const A = Symbol("A"); +>A : Symbol(A, Decl(contextuallyTypedSymbolNamedProperties.ts, 2, 5)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) + +const B = Symbol("B"); +>B : Symbol(B, Decl(contextuallyTypedSymbolNamedProperties.ts, 3, 5)) +>Symbol : Symbol(Symbol, Decl(lib.es5.d.ts, --, --), Decl(lib.es2015.symbol.d.ts, --, --), Decl(lib.es2015.symbol.wellknown.d.ts, --, --), Decl(lib.es2019.symbol.d.ts, --, --)) + +type Action = +>Action : Symbol(Action, Decl(contextuallyTypedSymbolNamedProperties.ts, 3, 22)) + + | {type: typeof A, data: string} +>type : Symbol(type, Decl(contextuallyTypedSymbolNamedProperties.ts, 6, 7)) +>A : Symbol(A, Decl(contextuallyTypedSymbolNamedProperties.ts, 2, 5)) +>data : Symbol(data, Decl(contextuallyTypedSymbolNamedProperties.ts, 6, 22)) + + | {type: typeof B, data: number} +>type : Symbol(type, Decl(contextuallyTypedSymbolNamedProperties.ts, 7, 7)) +>B : Symbol(B, Decl(contextuallyTypedSymbolNamedProperties.ts, 3, 5)) +>data : Symbol(data, Decl(contextuallyTypedSymbolNamedProperties.ts, 7, 22)) + +declare const ab: Action; +>ab : Symbol(ab, Decl(contextuallyTypedSymbolNamedProperties.ts, 9, 13)) +>Action : Symbol(Action, Decl(contextuallyTypedSymbolNamedProperties.ts, 3, 22)) + +declare function f(action: T, blah: { [K in T['type']]: (p: K) => void }): any; +>f : Symbol(f, Decl(contextuallyTypedSymbolNamedProperties.ts, 9, 25)) +>T : Symbol(T, Decl(contextuallyTypedSymbolNamedProperties.ts, 11, 19)) +>type : Symbol(type, Decl(contextuallyTypedSymbolNamedProperties.ts, 11, 30)) +>action : Symbol(action, Decl(contextuallyTypedSymbolNamedProperties.ts, 11, 56)) +>T : Symbol(T, Decl(contextuallyTypedSymbolNamedProperties.ts, 11, 19)) +>blah : Symbol(blah, Decl(contextuallyTypedSymbolNamedProperties.ts, 11, 66)) +>K : Symbol(K, Decl(contextuallyTypedSymbolNamedProperties.ts, 11, 76)) +>T : Symbol(T, Decl(contextuallyTypedSymbolNamedProperties.ts, 11, 19)) +>p : Symbol(p, Decl(contextuallyTypedSymbolNamedProperties.ts, 11, 94)) +>K : Symbol(K, Decl(contextuallyTypedSymbolNamedProperties.ts, 11, 76)) + +f(ab, { +>f : Symbol(f, Decl(contextuallyTypedSymbolNamedProperties.ts, 9, 25)) +>ab : Symbol(ab, Decl(contextuallyTypedSymbolNamedProperties.ts, 9, 13)) + + [A]: ap => { ap.description }, +>[A] : Symbol([A], Decl(contextuallyTypedSymbolNamedProperties.ts, 13, 7)) +>A : Symbol(A, Decl(contextuallyTypedSymbolNamedProperties.ts, 2, 5)) +>ap : Symbol(ap, Decl(contextuallyTypedSymbolNamedProperties.ts, 14, 8)) +>ap.description : Symbol(Symbol.description, Decl(lib.es2019.symbol.d.ts, --, --)) +>ap : Symbol(ap, Decl(contextuallyTypedSymbolNamedProperties.ts, 14, 8)) +>description : Symbol(Symbol.description, Decl(lib.es2019.symbol.d.ts, --, --)) + + [B]: bp => { bp.description }, +>[B] : Symbol([B], Decl(contextuallyTypedSymbolNamedProperties.ts, 14, 34)) +>B : Symbol(B, Decl(contextuallyTypedSymbolNamedProperties.ts, 3, 5)) +>bp : Symbol(bp, Decl(contextuallyTypedSymbolNamedProperties.ts, 15, 8)) +>bp.description : Symbol(Symbol.description, Decl(lib.es2019.symbol.d.ts, --, --)) +>bp : Symbol(bp, Decl(contextuallyTypedSymbolNamedProperties.ts, 15, 8)) +>description : Symbol(Symbol.description, Decl(lib.es2019.symbol.d.ts, --, --)) + +}) + +const x: { [sym: symbol]: (p: string) => void } = { [A]: s => s.length }; +>x : Symbol(x, Decl(contextuallyTypedSymbolNamedProperties.ts, 18, 5)) +>sym : Symbol(sym, Decl(contextuallyTypedSymbolNamedProperties.ts, 18, 12)) +>p : Symbol(p, Decl(contextuallyTypedSymbolNamedProperties.ts, 18, 27)) +>[A] : Symbol([A], Decl(contextuallyTypedSymbolNamedProperties.ts, 18, 51)) +>A : Symbol(A, Decl(contextuallyTypedSymbolNamedProperties.ts, 2, 5)) +>s : Symbol(s, Decl(contextuallyTypedSymbolNamedProperties.ts, 18, 56)) +>s.length : Symbol(String.length, Decl(lib.es5.d.ts, --, --)) +>s : Symbol(s, Decl(contextuallyTypedSymbolNamedProperties.ts, 18, 56)) +>length : Symbol(String.length, Decl(lib.es5.d.ts, --, --)) + diff --git a/tests/baselines/reference/contextuallyTypedSymbolNamedProperties.types b/tests/baselines/reference/contextuallyTypedSymbolNamedProperties.types new file mode 100644 index 00000000000..7f3da21666a --- /dev/null +++ b/tests/baselines/reference/contextuallyTypedSymbolNamedProperties.types @@ -0,0 +1,77 @@ +=== tests/cases/compiler/contextuallyTypedSymbolNamedProperties.ts === +// Repros from #43628 + +const A = Symbol("A"); +>A : unique symbol +>Symbol("A") : unique symbol +>Symbol : SymbolConstructor +>"A" : "A" + +const B = Symbol("B"); +>B : unique symbol +>Symbol("B") : unique symbol +>Symbol : SymbolConstructor +>"B" : "B" + +type Action = +>Action : Action + + | {type: typeof A, data: string} +>type : unique symbol +>A : unique symbol +>data : string + + | {type: typeof B, data: number} +>type : unique symbol +>B : unique symbol +>data : number + +declare const ab: Action; +>ab : Action + +declare function f(action: T, blah: { [K in T['type']]: (p: K) => void }): any; +>f : (action: T, blah: { [K in T["type"]]: (p: K) => void; }) => any +>type : string | symbol +>action : T +>blah : { [K in T["type"]]: (p: K) => void; } +>p : K + +f(ab, { +>f(ab, { [A]: ap => { ap.description }, [B]: bp => { bp.description },}) : any +>f : (action: T, blah: { [K in T["type"]]: (p: K) => void; }) => any +>ab : Action +>{ [A]: ap => { ap.description }, [B]: bp => { bp.description },} : { [A]: (ap: unique symbol) => void; [B]: (bp: unique symbol) => void; } + + [A]: ap => { ap.description }, +>[A] : (ap: unique symbol) => void +>A : unique symbol +>ap => { ap.description } : (ap: unique symbol) => void +>ap : unique symbol +>ap.description : string | undefined +>ap : unique symbol +>description : string | undefined + + [B]: bp => { bp.description }, +>[B] : (bp: unique symbol) => void +>B : unique symbol +>bp => { bp.description } : (bp: unique symbol) => void +>bp : unique symbol +>bp.description : string | undefined +>bp : unique symbol +>description : string | undefined + +}) + +const x: { [sym: symbol]: (p: string) => void } = { [A]: s => s.length }; +>x : { [sym: symbol]: (p: string) => void; } +>sym : symbol +>p : string +>{ [A]: s => s.length } : { [A]: (s: string) => number; } +>[A] : (s: string) => number +>A : unique symbol +>s => s.length : (s: string) => number +>s : string +>s.length : number +>s : string +>length : number + diff --git a/tests/cases/compiler/contextuallyTypedSymbolNamedProperties.ts b/tests/cases/compiler/contextuallyTypedSymbolNamedProperties.ts new file mode 100644 index 00000000000..c04f8046565 --- /dev/null +++ b/tests/cases/compiler/contextuallyTypedSymbolNamedProperties.ts @@ -0,0 +1,23 @@ +// @strict: true +// @declaration: true +// @target: esnext + +// Repros from #43628 + +const A = Symbol("A"); +const B = Symbol("B"); + +type Action = + | {type: typeof A, data: string} + | {type: typeof B, data: number} + +declare const ab: Action; + +declare function f(action: T, blah: { [K in T['type']]: (p: K) => void }): any; + +f(ab, { + [A]: ap => { ap.description }, + [B]: bp => { bp.description }, +}) + +const x: { [sym: symbol]: (p: string) => void } = { [A]: s => s.length };