diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index ebe2d1c84b5..7a708089444 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -26907,6 +26907,14 @@ namespace ts { const lhsType = getTypeOfExpression(e.expression); return isPrivateIdentifier(e.name) ? tryGetPrivateIdentifierPropertyOfType(lhsType, e.name) : getPropertyOfType(lhsType, e.name.escapedText); } + if (isElementAccessExpression(e)) { + const propType = checkExpressionCached(e.argumentExpression); + if (!isTypeUsableAsPropertyName(propType)) { + return undefined; + } + const lhsType = getTypeOfExpression(e.expression); + return getPropertyOfType(lhsType, getPropertyNameFromType(propType)); + } return undefined; function tryGetPrivateIdentifierPropertyOfType(type: Type, id: PrivateIdentifier) { diff --git a/tests/baselines/reference/classPropInitializationInferenceWithElementAccess.symbols b/tests/baselines/reference/classPropInitializationInferenceWithElementAccess.symbols new file mode 100644 index 00000000000..d8916efa2bf --- /dev/null +++ b/tests/baselines/reference/classPropInitializationInferenceWithElementAccess.symbols @@ -0,0 +1,41 @@ +=== tests/cases/compiler/classPropInitializationInferenceWithElementAccess.ts === +// repro #49339 +export class Cls { +>Cls : Symbol(Cls, Decl(classPropInitializationInferenceWithElementAccess.ts, 0, 0)) + + x; +>x : Symbol(Cls.x, Decl(classPropInitializationInferenceWithElementAccess.ts, 1, 18)) + + y; +>y : Symbol(Cls.y, Decl(classPropInitializationInferenceWithElementAccess.ts, 2, 6)) + + z; +>z : Symbol(Cls.z, Decl(classPropInitializationInferenceWithElementAccess.ts, 3, 6)) + + 0; +>0 : Symbol(Cls[0], Decl(classPropInitializationInferenceWithElementAccess.ts, 4, 6)) + + constructor(seed: number) { +>seed : Symbol(seed, Decl(classPropInitializationInferenceWithElementAccess.ts, 8, 16)) + + this['x'] = [seed]; +>this : Symbol(Cls, Decl(classPropInitializationInferenceWithElementAccess.ts, 0, 0)) +>'x' : Symbol(Cls.x, Decl(classPropInitializationInferenceWithElementAccess.ts, 1, 18)) +>seed : Symbol(seed, Decl(classPropInitializationInferenceWithElementAccess.ts, 8, 16)) + + this['y'] = { seed }; +>this : Symbol(Cls, Decl(classPropInitializationInferenceWithElementAccess.ts, 0, 0)) +>'y' : Symbol(Cls.y, Decl(classPropInitializationInferenceWithElementAccess.ts, 2, 6)) +>seed : Symbol(seed, Decl(classPropInitializationInferenceWithElementAccess.ts, 10, 21)) + + this['z'] = `${seed}`; +>this : Symbol(Cls, Decl(classPropInitializationInferenceWithElementAccess.ts, 0, 0)) +>'z' : Symbol(Cls.z, Decl(classPropInitializationInferenceWithElementAccess.ts, 3, 6)) +>seed : Symbol(seed, Decl(classPropInitializationInferenceWithElementAccess.ts, 8, 16)) + + this[0] = [seed]; +>this : Symbol(Cls, Decl(classPropInitializationInferenceWithElementAccess.ts, 0, 0)) +>0 : Symbol(Cls[0], Decl(classPropInitializationInferenceWithElementAccess.ts, 4, 6)) +>seed : Symbol(seed, Decl(classPropInitializationInferenceWithElementAccess.ts, 8, 16)) + } +} diff --git a/tests/baselines/reference/classPropInitializationInferenceWithElementAccess.types b/tests/baselines/reference/classPropInitializationInferenceWithElementAccess.types new file mode 100644 index 00000000000..397394b2350 --- /dev/null +++ b/tests/baselines/reference/classPropInitializationInferenceWithElementAccess.types @@ -0,0 +1,53 @@ +=== tests/cases/compiler/classPropInitializationInferenceWithElementAccess.ts === +// repro #49339 +export class Cls { +>Cls : Cls + + x; +>x : number[] + + y; +>y : { seed: number; } + + z; +>z : string + + 0; +>0 : number[] + + constructor(seed: number) { +>seed : number + + this['x'] = [seed]; +>this['x'] = [seed] : number[] +>this['x'] : number[] +>this : this +>'x' : "x" +>[seed] : number[] +>seed : number + + this['y'] = { seed }; +>this['y'] = { seed } : { seed: number; } +>this['y'] : { seed: number; } +>this : this +>'y' : "y" +>{ seed } : { seed: number; } +>seed : number + + this['z'] = `${seed}`; +>this['z'] = `${seed}` : string +>this['z'] : string +>this : this +>'z' : "z" +>`${seed}` : string +>seed : number + + this[0] = [seed]; +>this[0] = [seed] : number[] +>this[0] : number[] +>this : this +>0 : 0 +>[seed] : number[] +>seed : number + } +} diff --git a/tests/cases/compiler/classPropInitializationInferenceWithElementAccess.ts b/tests/cases/compiler/classPropInitializationInferenceWithElementAccess.ts new file mode 100644 index 00000000000..7bd1920a7d6 --- /dev/null +++ b/tests/cases/compiler/classPropInitializationInferenceWithElementAccess.ts @@ -0,0 +1,19 @@ +// @noEmit: true +// @strict: true + +// repro #49339 +export class Cls { + x; + y; + z; + + 0; + + constructor(seed: number) { + this['x'] = [seed]; + this['y'] = { seed }; + this['z'] = `${seed}`; + + this[0] = [seed]; + } +} \ No newline at end of file