From e4ad97f78b4a208e1148b65b26e3039d237688c7 Mon Sep 17 00:00:00 2001 From: David Blass Date: Wed, 6 Dec 2023 06:03:26 -0500 Subject: [PATCH] fix a bug preventing a subclass property sharing a name with a type parameter from being accessed --- src/compiler/checker.ts | 3 +- ...assPropertySharingNameWithTypeParameter.js | 44 +++++++++++++++++++ ...opertySharingNameWithTypeParameter.symbols | 22 ++++++++++ ...PropertySharingNameWithTypeParameter.types | 22 ++++++++++ ...assPropertySharingNameWithTypeParameter.ts | 8 ++++ 5 files changed, 98 insertions(+), 1 deletion(-) create mode 100644 tests/baselines/reference/classPropertySharingNameWithTypeParameter.js create mode 100644 tests/baselines/reference/classPropertySharingNameWithTypeParameter.symbols create mode 100644 tests/baselines/reference/classPropertySharingNameWithTypeParameter.types create mode 100644 tests/cases/compiler/classPropertySharingNameWithTypeParameter.ts diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index bd2d5f99899bc..204c5dcd7a73d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -13062,7 +13062,8 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker { const symbolTable = createSymbolTable(); // copy all symbols (except type parameters), including the ones with internal names like `InternalSymbolName.Index` for (const symbol of members.values()) { - if (!(symbol.flags & SymbolFlags.TypeParameter)) { + // include declared properties that share a name with a type parameter by checking for multiple declarations + if (!(symbol.flags & SymbolFlags.TypeParameter) || symbol.declarations?.some(declaration => declaration.kind !== SyntaxKind.TypeParameter)) { symbolTable.set(symbol.escapedName, symbol); } } diff --git a/tests/baselines/reference/classPropertySharingNameWithTypeParameter.js b/tests/baselines/reference/classPropertySharingNameWithTypeParameter.js new file mode 100644 index 0000000000000..fff779941b8fe --- /dev/null +++ b/tests/baselines/reference/classPropertySharingNameWithTypeParameter.js @@ -0,0 +1,44 @@ +//// [tests/cases/compiler/classPropertySharingNameWithTypeParameter.ts] //// + +//// [classPropertySharingNameWithTypeParameter.ts] +class Leg {} + +class Foo extends Leg { + t = {} as t + + // should allow this access since t was declared as a property on Foo + foo = this.t +} + +//// [classPropertySharingNameWithTypeParameter.js] +var __extends = (this && this.__extends) || (function () { + var extendStatics = function (d, b) { + extendStatics = Object.setPrototypeOf || + ({ __proto__: [] } instanceof Array && function (d, b) { d.__proto__ = b; }) || + function (d, b) { for (var p in b) if (Object.prototype.hasOwnProperty.call(b, p)) d[p] = b[p]; }; + return extendStatics(d, b); + }; + return function (d, b) { + if (typeof b !== "function" && b !== null) + throw new TypeError("Class extends value " + String(b) + " is not a constructor or null"); + extendStatics(d, b); + function __() { this.constructor = d; } + d.prototype = b === null ? Object.create(b) : (__.prototype = b.prototype, new __()); + }; +})(); +var Leg = /** @class */ (function () { + function Leg() { + } + return Leg; +}()); +var Foo = /** @class */ (function (_super) { + __extends(Foo, _super); + function Foo() { + var _this = _super !== null && _super.apply(this, arguments) || this; + _this.t = {}; + // should allow this access since t was declared as a property on Foo + _this.foo = _this.t; + return _this; + } + return Foo; +}(Leg)); diff --git a/tests/baselines/reference/classPropertySharingNameWithTypeParameter.symbols b/tests/baselines/reference/classPropertySharingNameWithTypeParameter.symbols new file mode 100644 index 0000000000000..a7fe1567c3a98 --- /dev/null +++ b/tests/baselines/reference/classPropertySharingNameWithTypeParameter.symbols @@ -0,0 +1,22 @@ +//// [tests/cases/compiler/classPropertySharingNameWithTypeParameter.ts] //// + +=== classPropertySharingNameWithTypeParameter.ts === +class Leg {} +>Leg : Symbol(Leg, Decl(classPropertySharingNameWithTypeParameter.ts, 0, 0)) + +class Foo extends Leg { +>Foo : Symbol(Foo, Decl(classPropertySharingNameWithTypeParameter.ts, 0, 12)) +>t : Symbol(t, Decl(classPropertySharingNameWithTypeParameter.ts, 2, 10), Decl(classPropertySharingNameWithTypeParameter.ts, 2, 26)) +>Leg : Symbol(Leg, Decl(classPropertySharingNameWithTypeParameter.ts, 0, 0)) + + t = {} as t +>t : Symbol(t, Decl(classPropertySharingNameWithTypeParameter.ts, 2, 10), Decl(classPropertySharingNameWithTypeParameter.ts, 2, 26)) +>t : Symbol(t, Decl(classPropertySharingNameWithTypeParameter.ts, 2, 10), Decl(classPropertySharingNameWithTypeParameter.ts, 2, 26)) + + // should allow this access since t was declared as a property on Foo + foo = this.t +>foo : Symbol(Foo.foo, Decl(classPropertySharingNameWithTypeParameter.ts, 3, 15)) +>this.t : Symbol(t, Decl(classPropertySharingNameWithTypeParameter.ts, 2, 10), Decl(classPropertySharingNameWithTypeParameter.ts, 2, 26)) +>this : Symbol(Foo, Decl(classPropertySharingNameWithTypeParameter.ts, 0, 12)) +>t : Symbol(t, Decl(classPropertySharingNameWithTypeParameter.ts, 2, 10), Decl(classPropertySharingNameWithTypeParameter.ts, 2, 26)) +} diff --git a/tests/baselines/reference/classPropertySharingNameWithTypeParameter.types b/tests/baselines/reference/classPropertySharingNameWithTypeParameter.types new file mode 100644 index 0000000000000..33e686ba2717c --- /dev/null +++ b/tests/baselines/reference/classPropertySharingNameWithTypeParameter.types @@ -0,0 +1,22 @@ +//// [tests/cases/compiler/classPropertySharingNameWithTypeParameter.ts] //// + +=== classPropertySharingNameWithTypeParameter.ts === +class Leg {} +>Leg : Leg + +class Foo extends Leg { +>Foo : Foo +>Leg : Leg + + t = {} as t +>t : t +>{} as t : t +>{} : {} + + // should allow this access since t was declared as a property on Foo + foo = this.t +>foo : t +>this.t : t +>this : this +>t : t +} diff --git a/tests/cases/compiler/classPropertySharingNameWithTypeParameter.ts b/tests/cases/compiler/classPropertySharingNameWithTypeParameter.ts new file mode 100644 index 0000000000000..79c8680d8a516 --- /dev/null +++ b/tests/cases/compiler/classPropertySharingNameWithTypeParameter.ts @@ -0,0 +1,8 @@ +class Leg {} + +class Foo extends Leg { + t = {} as t + + // should allow this access since t was declared as a property on Foo + foo = this.t +} \ No newline at end of file