@@ -3322,7 +3322,7 @@ namespace ts {
3322
3322
type;
3323
3323
}
3324
3324
3325
- function getTypeForVariableLikeDeclarationFromJSDocComment (declaration: VariableLikeDeclaration ) {
3325
+ function getTypeForDeclarationFromJSDocComment (declaration: Node ) {
3326
3326
const jsdocType = getJSDocType(declaration);
3327
3327
if (jsdocType) {
3328
3328
return getTypeFromTypeNode(jsdocType);
@@ -3350,7 +3350,7 @@ namespace ts {
3350
3350
// If this is a variable in a JavaScript file, then use the JSDoc type (if it has
3351
3351
// one as its type), otherwise fallback to the below standard TS codepaths to
3352
3352
// try to figure it out.
3353
- const type = getTypeForVariableLikeDeclarationFromJSDocComment (declaration);
3353
+ const type = getTypeForDeclarationFromJSDocComment (declaration);
3354
3354
if (type && type !== unknownType) {
3355
3355
return type;
3356
3356
}
@@ -3445,6 +3445,27 @@ namespace ts {
3445
3445
return undefined;
3446
3446
}
3447
3447
3448
+ // Return the inferred type for a variable, parameter, or property declaration
3449
+ function getTypeForJSSpecialPropertyDeclaration(declaration: Declaration): Type {
3450
+ const expression = declaration.kind === SyntaxKind.BinaryExpression ? <BinaryExpression>declaration :
3451
+ declaration.kind === SyntaxKind.PropertyAccessExpression ? <BinaryExpression>getAncestor(declaration, SyntaxKind.BinaryExpression) :
3452
+ undefined;
3453
+
3454
+ if (!expression) {
3455
+ return unknownType;
3456
+ }
3457
+
3458
+ if (expression.flags & NodeFlags.JavaScriptFile) {
3459
+ // If there is a JSDoc type, use it
3460
+ const type = getTypeForDeclarationFromJSDocComment(expression.parent);
3461
+ if (type && type !== unknownType) {
3462
+ return getWidenedType(type);
3463
+ }
3464
+ }
3465
+
3466
+ return getWidenedLiteralType(checkExpressionCached(expression.right));
3467
+ }
3468
+
3448
3469
// Return the type implied by a binding pattern element. This is the type of the initializer of the element if
3449
3470
// one is present. Otherwise, if the element is itself a binding pattern, it is the type implied by the binding
3450
3471
// pattern. Otherwise, it is the type any.
@@ -3599,18 +3620,7 @@ namespace ts {
3599
3620
// * className.prototype.method = expr
3600
3621
if (declaration.kind === SyntaxKind.BinaryExpression ||
3601
3622
declaration.kind === SyntaxKind.PropertyAccessExpression && declaration.parent.kind === SyntaxKind.BinaryExpression) {
3602
- // Use JS Doc type if present on parent expression statement
3603
- if (declaration.flags & NodeFlags.JavaScriptFile) {
3604
- const jsdocType = getJSDocType(declaration.parent);
3605
- if (jsdocType) {
3606
- return links.type = getTypeFromTypeNode(jsdocType);
3607
- }
3608
- }
3609
- const declaredTypes = map(symbol.declarations,
3610
- decl => decl.kind === SyntaxKind.BinaryExpression ?
3611
- checkExpressionCached((<BinaryExpression>decl).right) :
3612
- checkExpressionCached((<BinaryExpression>decl.parent).right));
3613
- type = getUnionType(declaredTypes, /*subtypeReduction*/ true);
3623
+ type = getWidenedType(getUnionType(map(symbol.declarations, getTypeForJSSpecialPropertyDeclaration), /*subtypeReduction*/ true));
3614
3624
}
3615
3625
else {
3616
3626
type = getWidenedTypeForVariableLikeDeclaration(<VariableLikeDeclaration>declaration, /*reportErrors*/ true);
@@ -3653,7 +3663,7 @@ namespace ts {
3653
3663
const setter = <AccessorDeclaration>getDeclarationOfKind(symbol, SyntaxKind.SetAccessor);
3654
3664
3655
3665
if (getter && getter.flags & NodeFlags.JavaScriptFile) {
3656
- const jsDocType = getTypeForVariableLikeDeclarationFromJSDocComment (getter);
3666
+ const jsDocType = getTypeForDeclarationFromJSDocComment (getter);
3657
3667
if (jsDocType) {
3658
3668
return links.type = jsDocType;
3659
3669
}
@@ -9535,11 +9545,19 @@ namespace ts {
9535
9545
}
9536
9546
9537
9547
function getAssignedTypeOfBinaryExpression(node: BinaryExpression): Type {
9538
- return node.parent.kind === SyntaxKind.ArrayLiteralExpression || node.parent.kind === SyntaxKind.PropertyAssignment ?
9548
+ const isDestructuringDefaultAssignment =
9549
+ node.parent.kind === SyntaxKind.ArrayLiteralExpression && isDestructuringAssignmentTarget(node.parent) ||
9550
+ node.parent.kind === SyntaxKind.PropertyAssignment && isDestructuringAssignmentTarget(node.parent.parent);
9551
+ return isDestructuringDefaultAssignment ?
9539
9552
getTypeWithDefault(getAssignedType(node), node.right) :
9540
9553
getTypeOfExpression(node.right);
9541
9554
}
9542
9555
9556
+ function isDestructuringAssignmentTarget(parent: Node) {
9557
+ return parent.parent.kind === SyntaxKind.BinaryExpression && (parent.parent as BinaryExpression).left === parent ||
9558
+ parent.parent.kind === SyntaxKind.ForOfStatement && (parent.parent as ForOfStatement).initializer === parent;
9559
+ }
9560
+
9543
9561
function getAssignedTypeOfArrayLiteralElement(node: ArrayLiteralExpression, element: Expression): Type {
9544
9562
return getTypeOfDestructuredArrayElement(getAssignedType(node), indexOf(node.elements, element));
9545
9563
}
0 commit comments