File tree 4 files changed +36
-3
lines changed
4 files changed +36
-3
lines changed Original file line number Diff line number Diff line change @@ -1961,7 +1961,7 @@ namespace ts {
1961
1961
classPrototype . parent = leftSideOfAssignment ;
1962
1962
1963
1963
const funcSymbol = container . locals [ constructorFunction . text ] ;
1964
- if ( ! funcSymbol || ! ( funcSymbol . flags & SymbolFlags . Function ) ) {
1964
+ if ( ! funcSymbol || ! ( funcSymbol . flags & SymbolFlags . Function || isDeclarationOfFunctionExpression ( funcSymbol ) ) ) {
1965
1965
return ;
1966
1966
}
1967
1967
Original file line number Diff line number Diff line change @@ -11495,8 +11495,12 @@ namespace ts {
11495
11495
// When resolved signature is a call signature (and not a construct signature) the result type is any, unless
11496
11496
// the declaring function had members created through 'x.prototype.y = expr' or 'this.y = expr' psuedodeclarations
11497
11497
// 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))) {
11500
11504
return getInferredClassType(funcSymbol);
11501
11505
}
11502
11506
else if (compilerOptions.noImplicitAny) {
Original file line number Diff line number Diff line change @@ -1264,6 +1264,18 @@ namespace ts {
1264
1264
return charCode === CharacterCodes . singleQuote || charCode === CharacterCodes . doubleQuote ;
1265
1265
}
1266
1266
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
+
1267
1279
/// Given a BinaryExpression, returns SpecialPropertyAssignmentKind for the various kinds of property
1268
1280
/// assignments we treat as special in the binder
1269
1281
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