File tree Expand file tree Collapse file tree
Expand file tree Collapse file tree Original file line number Diff line number Diff line change @@ -1961,7 +1961,7 @@ namespace ts {
19611961 classPrototype . parent = leftSideOfAssignment ;
19621962
19631963 const funcSymbol = container . locals [ constructorFunction . text ] ;
1964- if ( ! funcSymbol || ! ( funcSymbol . flags & SymbolFlags . Function ) ) {
1964+ if ( ! funcSymbol || ! ( funcSymbol . flags & SymbolFlags . Function || isDeclarationOfFunctionExpression ( funcSymbol ) ) ) {
19651965 return ;
19661966 }
19671967
Original file line number Diff line number Diff line change @@ -11495,8 +11495,12 @@ namespace ts {
1149511495 // When resolved signature is a call signature (and not a construct signature) the result type is any, unless
1149611496 // the declaring function had members created through 'x.prototype.y = expr' or 'this.y = expr' psuedodeclarations
1149711497 // in a JS file
11498- const funcSymbol = checkExpression(node.expression).symbol;
11499- if (funcSymbol && funcSymbol.members && (funcSymbol.flags & SymbolFlags.Function)) {
11498+ // Note:JS inferred classes might come from a variable declaration instead of a function declaration.
11499+ // In this case, using getResolvedSymbol directly is required to avoid losing the members from the declaration.
11500+ const funcSymbol = node.expression.kind === SyntaxKind.Identifier ?
11501+ getResolvedSymbol(node.expression as Identifier) :
11502+ checkExpression(node.expression).symbol;
11503+ if (funcSymbol && funcSymbol.members && (funcSymbol.flags & SymbolFlags.Function || isDeclarationOfFunctionExpression(funcSymbol))) {
1150011504 return getInferredClassType(funcSymbol);
1150111505 }
1150211506 else if (compilerOptions.noImplicitAny) {
Original file line number Diff line number Diff line change @@ -1264,6 +1264,18 @@ namespace ts {
12641264 return charCode === CharacterCodes . singleQuote || charCode === CharacterCodes . doubleQuote ;
12651265 }
12661266
1267+ /**
1268+ * Returns true if the node is a variable declaration whose initializer is a function expression.
1269+ * This function does not test if the node is in a JavaScript file or not.
1270+ */
1271+ export function isDeclarationOfFunctionExpression ( s : Symbol ) {
1272+ if ( s . valueDeclaration && s . valueDeclaration . kind === SyntaxKind . VariableDeclaration ) {
1273+ const declaration = s . valueDeclaration as VariableDeclaration ;
1274+ return declaration . initializer && declaration . initializer . kind === SyntaxKind . FunctionExpression ;
1275+ }
1276+ return false ;
1277+ }
1278+
12671279 /// Given a BinaryExpression, returns SpecialPropertyAssignmentKind for the various kinds of property
12681280 /// assignments we treat as special in the binder
12691281 export function getSpecialPropertyAssignmentKind ( expression : Node ) : SpecialPropertyAssignmentKind {
Original file line number Diff line number Diff line change 1+ /// <reference path="fourslash.ts" />
2+ // @allowJs : true
3+ // @Filename : something.js
4+ ////var C = function () { }
5+ /////**
6+ //// * The prototype method.
7+ //// * @param {string } a Parameter definition.
8+ //// */
9+ ////function f(a) {}
10+ ////C.prototype.m = f;
11+ ////
12+ ////var x = new C();
13+ ////x/*1*/./*2*/m();
14+ goTo . marker ( '1' ) ;
15+ verify . quickInfoIs ( 'var x: {\n m: (a: string) => void;\n}' ) ;
16+ goTo . marker ( '2' ) ;
17+ verify . completionListContains ( 'm' , '(property) C.m: (a: string) => void' , 'The prototype method.' ) ;
You can’t perform that action at this time.
0 commit comments