diff --git a/src/compiler/binder.ts b/src/compiler/binder.ts index 54d4c366739..c1f08f5d575 100644 --- a/src/compiler/binder.ts +++ b/src/compiler/binder.ts @@ -2042,6 +2042,8 @@ namespace ts { case SpecialPropertyAssignmentKind.PrototypeProperty: bindPrototypePropertyAssignment((node as BinaryExpression).left as PropertyAccessEntityNameExpression, node); break; + case SpecialPropertyAssignmentKind.Prototype: + bindPrototypeAssignment(node as BinaryExpression); case SpecialPropertyAssignmentKind.ThisProperty: bindThisPropertyAssignment(node as BinaryExpression); break; @@ -2361,8 +2363,13 @@ namespace ts { } } + /** For `x.prototype = { p, ... }`, declare members p,... if `x` is function/class/{}, or not declared. */ + function bindPrototypeAssignment(node: BinaryExpression) { + return node; + } + /** - * For 'x.prototype.y = z', declare a 'member' y on x if x is a function or class, or not declared. + * For `x.prototype.y = z`, declare a member `y` on `x` if `x` is a function or class, or not declared. * Note that jsdoc preceding an ExpressionStatement like `x.prototype.y;` is also treated as a declaration. */ function bindPrototypePropertyAssignment(lhs: PropertyAccessEntityNameExpression, parent: Node) { diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index 62113ed8dfd..518dd400c0d 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -14254,6 +14254,7 @@ namespace ts { case SpecialPropertyAssignmentKind.ModuleExports: case SpecialPropertyAssignmentKind.PrototypeProperty: case SpecialPropertyAssignmentKind.ThisProperty: + case SpecialPropertyAssignmentKind.Prototype: return false; default: Debug.assertNever(kind); diff --git a/src/compiler/types.ts b/src/compiler/types.ts index 39e4f90698d..cbccc071399 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3964,7 +3964,9 @@ namespace ts { /// this.name = expr ThisProperty, // F.name = expr - Property + Property, + // F.prototype = { ... } + Prototype, } export interface JsFileExtensionInfo { diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 69bba78929b..5760a8a18d1 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -1590,6 +1590,10 @@ namespace ts { return SpecialPropertyAssignmentKind.Property; } } + else if (lhs.name.escapedText === "prototype" && expr.right.kind === SyntaxKind.ObjectLiteralExpression) { + // F.prototype = { ... } + return SpecialPropertyAssignmentKind.Prototype; + } else if (lhs.expression.kind === SyntaxKind.ThisKeyword) { return SpecialPropertyAssignmentKind.ThisProperty; } diff --git a/src/services/navigationBar.ts b/src/services/navigationBar.ts index cdc7b2b1864..dd7f4175b71 100644 --- a/src/services/navigationBar.ts +++ b/src/services/navigationBar.ts @@ -275,6 +275,7 @@ namespace ts.NavigationBar { case SpecialPropertyAssignmentKind.ExportsProperty: case SpecialPropertyAssignmentKind.ModuleExports: case SpecialPropertyAssignmentKind.PrototypeProperty: + case SpecialPropertyAssignmentKind.Prototype: addNodeWithRecursiveChild(node, (node as BinaryExpression).right); break; case SpecialPropertyAssignmentKind.ThisProperty: diff --git a/src/services/utilities.ts b/src/services/utilities.ts index 263ac0f4c3b..51772b48441 100644 --- a/src/services/utilities.ts +++ b/src/services/utilities.ts @@ -370,6 +370,8 @@ namespace ts { case SpecialPropertyAssignmentKind.Property: // static method / property return isFunctionExpression(right) ? ScriptElementKind.memberFunctionElement : ScriptElementKind.memberVariableElement; + case SpecialPropertyAssignmentKind.Prototype: + return ScriptElementKind.localClassElement; default: { assertTypeIsNever(kind); return ScriptElementKind.unknown;