@@ -4255,10 +4255,12 @@ namespace ts {
42554255 return getWidenedLiteralType(checkExpressionCached(specialDeclaration));
42564256 }
42574257 const types: Type[] = [];
4258+ let constructorTypes: Type[];
42584259 let definedInConstructor = false;
42594260 let definedInMethod = false;
42604261 let jsDocType: Type;
42614262 for (const declaration of symbol.declarations) {
4263+ let declarationInConstructor = false;
42624264 const expression = declaration.kind === SyntaxKind.BinaryExpression ? <BinaryExpression>declaration :
42634265 declaration.kind === SyntaxKind.PropertyAccessExpression ? <BinaryExpression>getAncestor(declaration, SyntaxKind.BinaryExpression) :
42644266 undefined;
@@ -4271,9 +4273,10 @@ namespace ts {
42714273 const thisContainer = getThisContainer(expression, /*includeArrowFunctions*/ false);
42724274 // Properties defined in a constructor (or javascript constructor function) don't get undefined added.
42734275 // Function expressions that are assigned to the prototype count as methods.
4274- if ( thisContainer.kind === SyntaxKind.Constructor ||
4276+ declarationInConstructor = thisContainer.kind === SyntaxKind.Constructor ||
42754277 thisContainer.kind === SyntaxKind.FunctionDeclaration ||
4276- (thisContainer.kind === SyntaxKind.FunctionExpression && !isPrototypePropertyAssignment(thisContainer.parent))) {
4278+ (thisContainer.kind === SyntaxKind.FunctionExpression && !isPrototypePropertyAssignment(thisContainer.parent));
4279+ if (declarationInConstructor) {
42774280 definedInConstructor = true;
42784281 }
42794282 else {
@@ -4296,14 +4299,37 @@ namespace ts {
42964299 }
42974300 else if (!jsDocType) {
42984301 // If we don't have an explicit JSDoc type, get the type from the expression.
4299- types.push(getWidenedLiteralType(checkExpressionCached(expression.right)));
4302+ const type = getWidenedLiteralType(checkExpressionCached(expression.right));
4303+ let anyedType = type;
4304+ if (isEmptyArrayLiteralType(type)) {
4305+ anyedType = anyArrayType;
4306+ if (noImplicitAny) {
4307+ reportImplicitAnyError(expression, anyArrayType);
4308+ }
4309+ }
4310+ types.push(anyedType);
4311+ if (declarationInConstructor) {
4312+ (constructorTypes || (constructorTypes = [])).push(anyedType);
4313+ }
43004314 }
43014315 }
4302-
4303- const type = jsDocType || getUnionType(types, UnionReduction.Subtype);
4304- return getWidenedType(addOptionality(type, definedInMethod && !definedInConstructor));
4316+ let type = jsDocType;
4317+ if (!type) {
4318+ // use only the constructor types unless only null | undefined (including widening variants) were assigned there
4319+ const sourceTypes = some(constructorTypes, t => !!(t.flags & ~(TypeFlags.Nullable | TypeFlags.ContainsWideningType))) ? constructorTypes : types;
4320+ type = getUnionType(sourceTypes, UnionReduction.Subtype);
4321+ }
4322+ const widened = getWidenedType(addOptionality(type, definedInMethod && !definedInConstructor));
4323+ if (filterType(widened, t => !!(t.flags & ~TypeFlags.Nullable)) === neverType) {
4324+ if (noImplicitAny) {
4325+ reportImplicitAnyError(symbol.valueDeclaration, anyType);
4326+ }
4327+ return anyType;
4328+ }
4329+ return widened;
43054330 }
43064331
4332+
43074333 // Return the type implied by a binding pattern element. This is the type of the initializer of the element if
43084334 // one is present. Otherwise, if the element is itself a binding pattern, it is the type implied by the binding
43094335 // pattern. Otherwise, it is the type any.
@@ -11394,6 +11420,7 @@ namespace ts {
1139411420 const typeAsString = typeToString(getWidenedType(type));
1139511421 let diagnostic: DiagnosticMessage;
1139611422 switch (declaration.kind) {
11423+ case SyntaxKind.BinaryExpression:
1139711424 case SyntaxKind.PropertyDeclaration:
1139811425 case SyntaxKind.PropertySignature:
1139911426 diagnostic = Diagnostics.Member_0_implicitly_has_an_1_type;
@@ -19689,11 +19716,27 @@ namespace ts {
1968919716 }
1969019717
1969119718 function checkDeclarationInitializer(declaration: HasExpressionInitializer) {
19692- const initializer = isInJavaScriptFile(declaration) && getDeclaredJavascriptInitializer(declaration) || declaration.initializer;
19719+ const inJs = isInJavaScriptFile(declaration);
19720+ const initializer = inJs && getDeclaredJavascriptInitializer(declaration) || declaration.initializer;
1969319721 const type = getTypeOfExpression(initializer, /*cache*/ true);
19694- return getCombinedNodeFlags(declaration) & NodeFlags.Const ||
19722+ const widened = getCombinedNodeFlags(declaration) & NodeFlags.Const ||
1969519723 (getCombinedModifierFlags(declaration) & ModifierFlags.Readonly && !isParameterPropertyDeclaration(declaration)) ||
1969619724 isTypeAssertion(initializer) ? type : getWidenedLiteralType(type);
19725+ if (inJs) {
19726+ if (widened.flags & TypeFlags.Nullable) {
19727+ if (noImplicitAny) {
19728+ reportImplicitAnyError(declaration, anyType);
19729+ }
19730+ return anyType;
19731+ }
19732+ else if (isEmptyArrayLiteralType(widened)) {
19733+ if (noImplicitAny) {
19734+ reportImplicitAnyError(declaration, anyArrayType);
19735+ }
19736+ return anyArrayType;
19737+ }
19738+ }
19739+ return widened;
1969719740 }
1969819741
1969919742 function isLiteralOfContextualType(candidateType: Type, contextualType: Type): boolean {
0 commit comments