diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts index dc2d6649013..79f514e7864 100644 --- a/src/compiler/checker.ts +++ b/src/compiler/checker.ts @@ -6897,6 +6897,23 @@ namespace ts { const symbol = getSymbolOfNode(container.parent); return container.flags & NodeFlags.Static ? getTypeOfSymbol(symbol) : (getDeclaredTypeOfSymbol(symbol)).thisType; } + + // If this is a function in a JS file, it might be a class method. Check if it's the RHS + // of a x.prototype.y = function [name]() { .... } + if (isInJavaScriptFile(node) && container.kind === SyntaxKind.FunctionExpression) { + if (getSpecialPropertyAssignmentKind(container.parent) === SpecialPropertyAssignmentKind.PrototypeProperty) { + // Get the 'x' of 'x.prototype.y = f' (here, 'f' is 'container') + const className = (((container.parent as BinaryExpression) // x.protoype.y = f + .left as PropertyAccessExpression) // x.prototype.y + .expression as PropertyAccessExpression) // x.prototype + .expression; // x + const classSymbol = checkExpression(className).symbol; + if (classSymbol.members) { + return createAnonymousType(undefined, classSymbol.members, emptyArray, emptyArray, /*stringIndexType*/ undefined, /*numberIndexType*/ undefined); + } + } + } + return anyType; } diff --git a/tests/cases/fourslash/javaScriptPrototype3.ts b/tests/cases/fourslash/javaScriptPrototype3.ts new file mode 100644 index 00000000000..7b3f63eca57 --- /dev/null +++ b/tests/cases/fourslash/javaScriptPrototype3.ts @@ -0,0 +1,20 @@ +/// + +// Inside an inferred method body, the type of 'this' is the class type + +// @allowNonTsExtensions: true +// @Filename: myMod.js +//// function myCtor(x) { +//// this.qua = 10; +//// } +//// myCtor.prototype.foo = function() { return this/**/; }; +//// myCtor.prototype.bar = function() { return '' }; +//// + +goTo.marker(); +edit.insert('.'); + +// Check members of the function +verify.completionListContains('foo', undefined, undefined, 'property'); +verify.completionListContains('bar', undefined, undefined, 'property'); +verify.completionListContains('qua', undefined, undefined, 'property'); diff --git a/tests/cases/fourslash/javaScriptPrototype5.ts b/tests/cases/fourslash/javaScriptPrototype5.ts new file mode 100644 index 00000000000..a0125e47512 --- /dev/null +++ b/tests/cases/fourslash/javaScriptPrototype5.ts @@ -0,0 +1,19 @@ +/// + +// No prototype assignments are needed to enable class inference + +// @allowNonTsExtensions: true +// @Filename: myMod.js +//// function myCtor() { +//// this.foo = 'hello'; +//// this.bar = 10; +//// } +//// let x = new myCtor(); +//// x/**/ + +goTo.marker(); +edit.insert('.'); + +// Check members of the function +verify.completionListContains('foo', undefined, undefined, 'property'); +verify.completionListContains('bar', undefined, undefined, 'property');