@@ -4430,7 +4430,7 @@ namespace ts {
4430
4430
const special = getSpecialPropertyAssignmentKind(expression);
4431
4431
if (special === SpecialPropertyAssignmentKind.ThisProperty) {
4432
4432
const thisContainer = getThisContainer(expression, /*includeArrowFunctions*/ false);
4433
- // Properties defined in a constructor (or javascript constructor function) don't get undefined added.
4433
+ // Properties defined in a constructor (or base constructor, or javascript constructor function) don't get undefined added.
4434
4434
// Function expressions that are assigned to the prototype count as methods.
4435
4435
declarationInConstructor = thisContainer.kind === SyntaxKind.Constructor ||
4436
4436
thisContainer.kind === SyntaxKind.FunctionDeclaration ||
@@ -4500,7 +4500,14 @@ namespace ts {
4500
4500
}
4501
4501
let type = jsDocType;
4502
4502
if (!type) {
4503
- // use only the constructor types unless only null | undefined (including widening variants) were assigned there
4503
+ // use only the constructor types unless they were only assigned null | undefined (including widening variants)
4504
+ if (definedInMethod) {
4505
+ const propType = getTypeOfSpecialPropertyOfBaseType(symbol);
4506
+ if (propType) {
4507
+ (constructorTypes || (constructorTypes = [])).push(propType);
4508
+ definedInConstructor = true;
4509
+ }
4510
+ }
4504
4511
const sourceTypes = some(constructorTypes, t => !!(t.flags & ~(TypeFlags.Nullable | TypeFlags.ContainsWideningType))) ? constructorTypes : types;
4505
4512
type = getUnionType(sourceTypes, UnionReduction.Subtype);
4506
4513
}
@@ -4514,6 +4521,20 @@ namespace ts {
4514
4521
return widened;
4515
4522
}
4516
4523
4524
+ /** check for definition in base class if any declaration is in a class */
4525
+ function getTypeOfSpecialPropertyOfBaseType(specialProperty: Symbol) {
4526
+ const parentDeclaration = forEach(specialProperty.declarations, d => {
4527
+ const parent = getThisContainer(d, /*includeArrowFunctions*/ false).parent;
4528
+ return isClassLike(parent) && parent;
4529
+ });
4530
+ if (parentDeclaration) {
4531
+ const classType = getDeclaredTypeOfSymbol(getSymbolOfNode(parentDeclaration)) as InterfaceType;
4532
+ const baseClassType = classType && getBaseTypes(classType)[0];
4533
+ if (baseClassType) {
4534
+ return getTypeOfPropertyOfType(baseClassType, specialProperty.escapedName);
4535
+ }
4536
+ }
4537
+ }
4517
4538
4518
4539
// Return the type implied by a binding pattern element. This is the type of the initializer of the element if
4519
4540
// one is present. Otherwise, if the element is itself a binding pattern, it is the type implied by the binding
0 commit comments