@@ -5949,6 +5949,7 @@ namespace ts {
5949
5949
}
5950
5950
}
5951
5951
5952
+
5952
5953
// Synthesize declarations for a symbol - might be an Interface, a Class, a Namespace, a Type, a Variable (const, let, or var), an Alias
5953
5954
// or a merge of some number of those.
5954
5955
// An interesting challenge is ensuring that when classes merge with namespaces and interfaces, is keeping
@@ -6317,7 +6318,10 @@ namespace ts {
6317
6318
const baseTypes = getBaseTypes(classType);
6318
6319
const implementsTypes = getImplementsTypes(classType);
6319
6320
const staticType = getTypeOfSymbol(symbol);
6320
- const staticBaseType = getBaseConstructorTypeOfClass(staticType as InterfaceType);
6321
+ const isClass = !!staticType.symbol?.valueDeclaration && isClassLike(staticType.symbol.valueDeclaration);
6322
+ const staticBaseType = isClass
6323
+ ? getBaseConstructorTypeOfClass(staticType as InterfaceType)
6324
+ : anyType;
6321
6325
const heritageClauses = [
6322
6326
...!length(baseTypes) ? [] : [createHeritageClause(SyntaxKind.ExtendsKeyword, map(baseTypes, b => serializeBaseType(b, staticBaseType, localName)))],
6323
6327
...!length(implementsTypes) ? [] : [createHeritageClause(SyntaxKind.ImplementsKeyword, map(implementsTypes, b => serializeBaseType(b, staticBaseType, localName)))]
@@ -6353,7 +6357,17 @@ namespace ts {
6353
6357
const staticMembers = flatMap(
6354
6358
filter(getPropertiesOfType(staticType), p => !(p.flags & SymbolFlags.Prototype) && p.escapedName !== "prototype" && !isNamespaceMember(p)),
6355
6359
p => serializePropertySymbolForClass(p, /*isStatic*/ true, staticBaseType));
6356
- const constructors = serializeSignatures(SignatureKind.Construct, staticType, baseTypes[0], SyntaxKind.Constructor) as ConstructorDeclaration[];
6360
+ // When we encounter an `X.prototype.y` assignment in a JS file, we bind `X` as a class regardless as to whether
6361
+ // the value is ever initialized with a class or function-like value. For cases where `X` could never be
6362
+ // created via `new`, we will inject a `private constructor()` declaration to indicate it is not createable.
6363
+ const isNonConstructableClassLikeInJsFile =
6364
+ !isClass &&
6365
+ !!symbol.valueDeclaration &&
6366
+ isInJSFile(symbol.valueDeclaration) &&
6367
+ !some(getSignaturesOfType(staticType, SignatureKind.Construct));
6368
+ const constructors = isNonConstructableClassLikeInJsFile ?
6369
+ [createConstructor(/*decorators*/ undefined, createModifiersFromModifierFlags(ModifierFlags.Private), [], /*body*/ undefined)] :
6370
+ serializeSignatures(SignatureKind.Construct, staticType, baseTypes[0], SyntaxKind.Constructor) as ConstructorDeclaration[];
6357
6371
for (const c of constructors) {
6358
6372
// A constructor's return type and type parameters are supposed to be controlled by the enclosing class declaration
6359
6373
// `signatureToSignatureDeclarationHelper` appends them regardless, so for now we delete them here
0 commit comments