@@ -2049,6 +2049,7 @@ namespace ts {
2049
2049
const declaration = find(
2050
2050
result.declarations,
2051
2051
d => isBlockOrCatchScoped(d) || isClassLike(d) || (d.kind === SyntaxKind.EnumDeclaration));
2052
+
2052
2053
if (declaration === undefined) return Debug.fail("checkResolvedBlockScopedVariable could not find block-scoped declaration");
2053
2054
2054
2055
if (!(declaration.flags & NodeFlags.Ambient) && !isBlockScopedNameDeclaredBeforeUse(declaration, errorLocation)) {
@@ -5973,11 +5974,10 @@ namespace ts {
5973
5974
if (!links.type) {
5974
5975
const jsDeclaration = getDeclarationOfExpando(symbol.valueDeclaration);
5975
5976
if (jsDeclaration) {
5976
- const merged = jsMerge (symbol, getSymbolOfNode(jsDeclaration));
5977
+ const merged = mergeJSSymbols (symbol, getSymbolOfNode(jsDeclaration));
5977
5978
if (merged) {
5978
5979
// note:we overwrite links because we just cloned the symbol
5979
- symbol = merged;
5980
- links = merged;
5980
+ symbol = links = merged;
5981
5981
}
5982
5982
}
5983
5983
originalLinks.type = links.type = getTypeOfFuncClassEnumModuleWorker(symbol);
@@ -6153,6 +6153,7 @@ namespace ts {
6153
6153
while (true) {
6154
6154
node = node.parent; // TODO: GH#18217 Use SourceFile kind check instead
6155
6155
if (node && isBinaryExpression(node)) {
6156
+ // prototype assignments get the outer type parameters of their constructor function
6156
6157
const assignmentKind = getAssignmentDeclarationKind(node);
6157
6158
if (assignmentKind === AssignmentDeclarationKind.Prototype || assignmentKind === AssignmentDeclarationKind.PrototypeProperty) {
6158
6159
const symbol = getSymbolOfNode(node.left);
@@ -6249,7 +6250,7 @@ namespace ts {
6249
6250
const constraint = getBaseConstraintOfType(type);
6250
6251
return !!constraint && isValidBaseType(constraint) && isMixinConstructorType(constraint);
6251
6252
}
6252
- return isJSConstructorType(type) ;
6253
+ return false ;
6253
6254
}
6254
6255
6255
6256
function getBaseTypeNodeOfClass(type: InterfaceType): ExpressionWithTypeArguments | undefined {
@@ -6351,9 +6352,7 @@ namespace ts {
6351
6352
const baseTypeNode = getBaseTypeNodeOfClass(type)!;
6352
6353
const typeArgs = typeArgumentsFromTypeReferenceNode(baseTypeNode);
6353
6354
let baseType: Type;
6354
- const originalBaseType = isJSConstructorType(baseConstructorType) ? baseConstructorType :
6355
- baseConstructorType.symbol ? getDeclaredTypeOfSymbol(baseConstructorType.symbol) :
6356
- undefined;
6355
+ const originalBaseType = baseConstructorType.symbol ? getDeclaredTypeOfSymbol(baseConstructorType.symbol) : undefined;
6357
6356
if (baseConstructorType.symbol && baseConstructorType.symbol.flags & SymbolFlags.Class &&
6358
6357
areAllOuterTypeParametersApplied(originalBaseType!)) {
6359
6358
// When base constructor type is a class with no captured type arguments we know that the constructors all have the same type parameters as the
@@ -6364,9 +6363,6 @@ namespace ts {
6364
6363
else if (baseConstructorType.flags & TypeFlags.Any) {
6365
6364
baseType = baseConstructorType;
6366
6365
}
6367
- else if (isJSConstructorType(baseConstructorType)) {
6368
- baseType = !baseTypeNode.typeArguments && getJSClassType(baseConstructorType.symbol) || anyType;
6369
- }
6370
6366
else {
6371
6367
// The class derives from a "class-like" constructor function, check that we have at least one construct signature
6372
6368
// with a matching number of type parameters and use the return type of the first instantiated signature. Elsewhere
@@ -6478,32 +6474,15 @@ namespace ts {
6478
6474
return true;
6479
6475
}
6480
6476
6481
- function jsMerge(target: Symbol, source: Symbol | undefined) {
6482
- if (source && (hasEntries(source.exports) || hasEntries(source.members))) {
6483
- target = cloneSymbol(target);
6484
- if (hasEntries(source.exports)) {
6485
- target.exports = target.exports || createSymbolTable();
6486
- mergeSymbolTable(target.exports, source.exports);
6487
- }
6488
- if (hasEntries(source.members)) {
6489
- target.members = target.members || createSymbolTable();
6490
- mergeSymbolTable(target.members, source.members);
6491
- }
6492
- target.flags |= source.flags & SymbolFlags.Class;
6493
- return target as TransientSymbol;
6494
- }
6495
- }
6496
-
6497
6477
function getDeclaredTypeOfClassOrInterface(symbol: Symbol): InterfaceType {
6498
6478
let links = getSymbolLinks(symbol);
6499
6479
const originalLinks = links;
6500
6480
if (!links.declaredType) {
6501
6481
const kind = symbol.flags & SymbolFlags.Class ? ObjectFlags.Class : ObjectFlags.Interface;
6502
- const merged = jsMerge (symbol, getAssignedClassSymbol(symbol.valueDeclaration));
6482
+ const merged = mergeJSSymbols (symbol, getAssignedClassSymbol(symbol.valueDeclaration));
6503
6483
if (merged) {
6504
6484
// note:we overwrite links because we just cloned the symbol
6505
- symbol = merged;
6506
- links = merged;
6485
+ symbol = links = merged;
6507
6486
}
6508
6487
6509
6488
const type = originalLinks.declaredType = links.declaredType = <InterfaceType>createObjectType(kind, symbol);
@@ -7548,7 +7527,6 @@ namespace ts {
7548
7527
if (!constructSignatures.length) {
7549
7528
constructSignatures = getDefaultConstructSignatures(classType);
7550
7529
}
7551
-
7552
7530
type.constructSignatures = constructSignatures;
7553
7531
}
7554
7532
}
@@ -11123,15 +11101,17 @@ namespace ts {
11123
11101
}
11124
11102
}
11125
11103
11126
- // TODO: Make the symbol.parent approach as complete as getClassNameFromPrototypeMethod(container),
11127
- // then make getThisType and checkThisExpression both use that.
11104
+ // inside x.prototype = { ... }
11128
11105
if (parent && isObjectLiteralExpression(parent) && isBinaryExpression(parent.parent) && getAssignmentDeclarationKind(parent.parent) === AssignmentDeclarationKind.Prototype) {
11129
11106
return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(parent.parent.left)!.parent!).thisType!;
11130
11107
}
11108
+ // /** @return {this} */
11109
+ // x.prototype.m = function() { ... }
11131
11110
const host = node.flags & NodeFlags.JSDoc ? getHostSignatureFromJSDoc(node) : undefined;
11132
11111
if (host && isFunctionExpression(host) && isBinaryExpression(host.parent) && getAssignmentDeclarationKind(host.parent) === AssignmentDeclarationKind.PrototypeProperty) {
11133
11112
return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(host.parent.left)!.parent!).thisType!;
11134
11113
}
11114
+ // inside constructor function C() { ... }
11135
11115
if (isJSConstructor(container) && isNodeDescendantOf(node, container.body)) {
11136
11116
return getDeclaredTypeOfClassOrInterface(getSymbolOfNode(container)).thisType!;
11137
11117
}
@@ -12428,13 +12408,15 @@ namespace ts {
12428
12408
if (!ignoreReturnTypes) {
12429
12409
// If a signature resolution is already in-flight, skip issuing a circularity error
12430
12410
// here and just use the `any` type directly
12431
- const targetReturnType = isResolvingReturnTypeOfSignature(target) ? anyType : (target.declaration && isJSConstructor(target.declaration)) ?
12432
- getJSClassType(target.declaration.symbol)! : getReturnTypeOfSignature(target);
12411
+ const targetReturnType = isResolvingReturnTypeOfSignature(target) ? anyType
12412
+ : target.declaration && isJSConstructor(target.declaration) ? getDeclaredTypeOfClassOrInterface(target.declaration.symbol)
12413
+ : getReturnTypeOfSignature(target);
12433
12414
if (targetReturnType === voidType) {
12434
12415
return result;
12435
12416
}
12436
- const sourceReturnType = isResolvingReturnTypeOfSignature(source) ? anyType : (source.declaration && isJSConstructor(source.declaration)) ?
12437
- getJSClassType(source.declaration.symbol)! : getReturnTypeOfSignature(source);
12417
+ const sourceReturnType = isResolvingReturnTypeOfSignature(source) ? anyType
12418
+ : source.declaration && isJSConstructor(source.declaration) ? getDeclaredTypeOfClassOrInterface(source.declaration.symbol)
12419
+ : getReturnTypeOfSignature(source);
12438
12420
12439
12421
// The following block preserves behavior forbidding boolean returning functions from being assignable to type guard returning functions
12440
12422
const targetTypePredicate = getTypePredicateOfSignature(target);
@@ -18312,8 +18294,6 @@ namespace ts {
18312
18294
// If this is a function in a JS file, it might be a class method.
18313
18295
const className = getClassNameFromPrototypeMethod(container);
18314
18296
if (isInJS && className) {
18315
- // TODO: Why isn't this getSymbolOfNode(className).parent? Seems like it pulls way too early on the type
18316
- // (should be able to use the symbol.parent trick instead)
18317
18297
const classSymbol = checkExpression(className).symbol;
18318
18298
if (classSymbol && classSymbol.members && (classSymbol.flags & SymbolFlags.Function)) {
18319
18299
const classType = (getDeclaredTypeOfSymbol(classSymbol) as InterfaceType).thisType!;
@@ -18327,7 +18307,6 @@ namespace ts {
18327
18307
else if (isInJS &&
18328
18308
(container.kind === SyntaxKind.FunctionExpression || container.kind === SyntaxKind.FunctionDeclaration) &&
18329
18309
getJSDocClassTag(container)) {
18330
- // TODO: might be able to merge this code with the ClassLike path
18331
18310
const classType = (getDeclaredTypeOfSymbol(getMergedSymbol(container.symbol)) as InterfaceType).thisType!;
18332
18311
return getFlowTypeOfReference(node, classType);
18333
18312
}
@@ -22878,19 +22857,19 @@ namespace ts {
22878
22857
return false;
22879
22858
}
22880
22859
22881
- // TODO: This is probably wrong now (or redundant)
22882
- function isJSConstructorType(type: Type ) {
22883
- if (type.flags & TypeFlags.Object) {
22884
- const resolved = resolveStructuredTypeMembers(<ObjectType>type);
22885
- return resolved.callSignatures.length === 1 && isJSConstructor(resolved.callSignatures[0].declaration );
22886
- }
22887
- return false;
22888
- }
22889
-
22890
- // TODO: Remove this function
22891
- function getJSClassType(symbol: Symbol): Type | undefined {
22892
- if (isJSConstructor(symbol.valueDeclaration)) {
22893
- return getDeclaredTypeOfClassOrInterface(symbol) ;
22860
+ function mergeJSSymbols(target: Symbol, source: Symbol | undefined) {
22861
+ if (source && (hasEntries(source.exports) || hasEntries(source.members)) ) {
22862
+ target = cloneSymbol(target);
22863
+ if (hasEntries(source.exports)) {
22864
+ target.exports = target.exports || createSymbolTable( );
22865
+ mergeSymbolTable(target.exports, source.exports);
22866
+ }
22867
+ if (hasEntries(source.members)) {
22868
+ target.members = target.members || createSymbolTable();
22869
+ mergeSymbolTable(target.members, source.members);
22870
+ }
22871
+ target.flags |= source.flags & SymbolFlags.Class;
22872
+ return target as TransientSymbol ;
22894
22873
}
22895
22874
}
22896
22875
0 commit comments