@@ -27033,42 +27033,30 @@ export function createTypeChecker(host: TypeCheckerHost): TypeChecker {
2703327033 }
2703427034 return type;
2703527035 }
27036-
27037- // Check that right operand is a function type with a prototype property
27038- const rightType = getTypeOfExpression(expr.right);
27039- if (!isTypeDerivedFrom(rightType, globalFunctionType)) {
27036+ const instanceType = mapType(getTypeOfExpression(expr.right), getInstanceType);
27037+ // Don't narrow from `any` if the target type is exactly `Object` or `Function`, and narrow
27038+ // in the false branch only if the target is a non-empty object type.
27039+ if (isTypeAny(type) && (instanceType === globalObjectType || instanceType === globalFunctionType) ||
27040+ !assumeTrue && !(instanceType.flags & TypeFlags.Object && !isEmptyAnonymousObjectType(instanceType))) {
2704027041 return type;
2704127042 }
27043+ return getNarrowedType(type, instanceType, assumeTrue, /*checkDerived*/ true);
27044+ }
2704227045
27043- let targetType: Type | undefined;
27044- const prototypeProperty = getPropertyOfType(rightType, "prototype" as __String);
27045- if (prototypeProperty) {
27046- // Target type is type of the prototype property
27047- const prototypePropertyType = getTypeOfSymbol(prototypeProperty);
27048- if (!isTypeAny(prototypePropertyType)) {
27049- targetType = prototypePropertyType;
27046+ function getInstanceType(constructorType: Type) {
27047+ if (isTypeDerivedFrom(constructorType, globalFunctionType)) {
27048+ const prototypePropertyType = getTypeOfPropertyOfType(constructorType, "prototype" as __String);
27049+ if (prototypePropertyType && !isTypeAny(prototypePropertyType)) {
27050+ return prototypePropertyType;
27051+ }
27052+ const constructSignatures = getSignaturesOfType(constructorType, SignatureKind.Construct);
27053+ if (constructSignatures.length) {
27054+ return getUnionType(map(constructSignatures, signature => getReturnTypeOfSignature(getErasedSignature(signature))));
2705027055 }
2705127056 }
27052-
27053- // Don't narrow from 'any' if the target type is exactly 'Object' or 'Function'
27054- if (isTypeAny(type) && (targetType === globalObjectType || targetType === globalFunctionType)) {
27055- return type;
27056- }
27057-
27058- if (!targetType) {
27059- const constructSignatures = getSignaturesOfType(rightType, SignatureKind.Construct);
27060- targetType = constructSignatures.length ?
27061- getUnionType(map(constructSignatures, signature => getReturnTypeOfSignature(getErasedSignature(signature)))) :
27062- emptyObjectType;
27063- }
27064-
27065- // We can't narrow a union based off instanceof without negated types see #31576 for more info
27066- if (!assumeTrue && rightType.flags & TypeFlags.Union) {
27067- const nonConstructorTypeInUnion = find((rightType as UnionType).types, (t) => !isConstructorType(t));
27068- if (!nonConstructorTypeInUnion) return type;
27069- }
27070-
27071- return getNarrowedType(type, targetType, assumeTrue, /*checkDerived*/ true);
27057+ // We use the empty object type to indicate we don't know the type of objects created by
27058+ // this constructor function.
27059+ return emptyObjectType;
2707227060 }
2707327061
2707427062 function getNarrowedType(type: Type, candidate: Type, assumeTrue: boolean, checkDerived: boolean) {
0 commit comments