@@ -5949,24 +5949,6 @@ namespace ts {
5949
5949
}
5950
5950
}
5951
5951
5952
- function isEffectiveClassSymbol(symbol: Symbol) {
5953
- if (!(symbol.flags & SymbolFlags.Class)) {
5954
- return false;
5955
- }
5956
- if (isInJSFile(symbol.valueDeclaration) && !isClassLike(symbol.valueDeclaration)) {
5957
- // For a symbol that isn't syntactically a `class` in a JS file we have heuristics
5958
- // that detect prototype assignments that indicate the symbol is *probably* a class.
5959
- // Filter out any prototype assignments for non-class symbols, i.e.
5960
- //
5961
- // let A;
5962
- // A = {};
5963
- // A.prototype.b = {};
5964
- const type = getTypeOfSymbol(symbol);
5965
- return some(getSignaturesOfType(type, SignatureKind.Construct))
5966
- || some(getSignaturesOfType(type, SignatureKind.Call));
5967
- }
5968
- return true;
5969
- }
5970
5952
5971
5953
// Synthesize declarations for a symbol - might be an Interface, a Class, a Namespace, a Type, a Variable (const, let, or var), an Alias
5972
5954
// or a merge of some number of those.
@@ -6009,14 +5991,14 @@ namespace ts {
6009
5991
if (symbol.flags & (SymbolFlags.BlockScopedVariable | SymbolFlags.FunctionScopedVariable | SymbolFlags.Property)
6010
5992
&& symbol.escapedName !== InternalSymbolName.ExportEquals
6011
5993
&& !(symbol.flags & SymbolFlags.Prototype)
6012
- && !isEffectiveClassSymbol (symbol)
5994
+ && !(symbol.flags & SymbolFlags.Class )
6013
5995
&& !isConstMergedWithNSPrintableAsSignatureMerge) {
6014
5996
serializeVariableOrProperty(symbol, symbolName, isPrivate, needsPostExportDefault, propertyAsAlias, modifierFlags);
6015
5997
}
6016
5998
if (symbol.flags & SymbolFlags.Enum) {
6017
5999
serializeEnum(symbol, symbolName, modifierFlags);
6018
6000
}
6019
- if (isEffectiveClassSymbol( symbol) ) {
6001
+ if (symbol.flags & SymbolFlags.Class ) {
6020
6002
if (symbol.flags & SymbolFlags.Property && isBinaryExpression(symbol.valueDeclaration.parent) && isClassExpression(symbol.valueDeclaration.parent.right)) {
6021
6003
// Looks like a `module.exports.Sub = class {}` - if we serialize `symbol` as a class, the result will have no members,
6022
6004
// since the classiness is actually from the target of the effective alias the symbol is. yes. A BlockScopedVariable|Class|Property
@@ -6336,7 +6318,8 @@ namespace ts {
6336
6318
const baseTypes = getBaseTypes(classType);
6337
6319
const implementsTypes = getImplementsTypes(classType);
6338
6320
const staticType = getTypeOfSymbol(symbol);
6339
- const staticBaseType = staticType.symbol?.valueDeclaration && isClassLike(staticType.symbol.valueDeclaration)
6321
+ const isClass = !!staticType.symbol?.valueDeclaration && isClassLike(staticType.symbol.valueDeclaration);
6322
+ const staticBaseType = isClass
6340
6323
? getBaseConstructorTypeOfClass(staticType as InterfaceType)
6341
6324
: anyType;
6342
6325
const heritageClauses = [
@@ -6374,7 +6357,17 @@ namespace ts {
6374
6357
const staticMembers = flatMap(
6375
6358
filter(getPropertiesOfType(staticType), p => !(p.flags & SymbolFlags.Prototype) && p.escapedName !== "prototype" && !isNamespaceMember(p)),
6376
6359
p => serializePropertySymbolForClass(p, /*isStatic*/ true, staticBaseType));
6377
- 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[];
6378
6371
for (const c of constructors) {
6379
6372
// A constructor's return type and type parameters are supposed to be controlled by the enclosing class declaration
6380
6373
// `signatureToSignatureDeclarationHelper` appends them regardless, so for now we delete them here
0 commit comments