@@ -7393,6 +7393,24 @@ namespace ts {
7393
7393
};
7394
7394
}
7395
7395
7396
+ // Return true if the given type could possibly reference a type parameter for which
7397
+ // we perform type inference (i.e. a type parameter of a generic function). We cache
7398
+ // results for union and intersection types for performance reasons.
7399
+ function couldContainTypeParameters(type: Type): boolean {
7400
+ return !!(type.flags & TypeFlags.TypeParameter ||
7401
+ type.flags & TypeFlags.Reference && forEach((<TypeReference>type).typeArguments, couldContainTypeParameters) ||
7402
+ type.flags & TypeFlags.Tuple && forEach((<TupleType>type).elementTypes, couldContainTypeParameters) ||
7403
+ type.flags & TypeFlags.Anonymous && type.symbol && type.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class) ||
7404
+ type.flags & TypeFlags.UnionOrIntersection && couldUnionOrIntersectionContainTypeParameters(<UnionOrIntersectionType>type));
7405
+ }
7406
+
7407
+ function couldUnionOrIntersectionContainTypeParameters(type: UnionOrIntersectionType): boolean {
7408
+ if (type.couldContainTypeParameters === undefined) {
7409
+ type.couldContainTypeParameters = forEach(type.types, couldContainTypeParameters);
7410
+ }
7411
+ return type.couldContainTypeParameters;
7412
+ }
7413
+
7396
7414
function inferTypes(context: InferenceContext, source: Type, target: Type) {
7397
7415
let sourceStack: Type[];
7398
7416
let targetStack: Type[];
@@ -7411,6 +7429,9 @@ namespace ts {
7411
7429
}
7412
7430
7413
7431
function inferFromTypes(source: Type, target: Type) {
7432
+ if (!couldContainTypeParameters(target)) {
7433
+ return;
7434
+ }
7414
7435
if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union && !(source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum) ||
7415
7436
source.flags & TypeFlags.Intersection && target.flags & TypeFlags.Intersection) {
7416
7437
// Source and target are both unions or both intersections. If source and target
@@ -7521,25 +7542,18 @@ namespace ts {
7521
7542
}
7522
7543
else {
7523
7544
source = getApparentType(source);
7524
- if (source.flags & TypeFlags.ObjectType && (
7525
- target.flags & TypeFlags.Reference && (<TypeReference>target).typeArguments ||
7526
- target.flags & TypeFlags.Tuple ||
7527
- target.flags & TypeFlags.Anonymous && target.symbol && target.symbol.flags & (SymbolFlags.Method | SymbolFlags.TypeLiteral | SymbolFlags.Class))) {
7528
- // If source is an object type, and target is a type reference with type arguments, a tuple type,
7529
- // the type of a method, or a type literal, infer from members
7545
+ if (source.flags & TypeFlags.ObjectType) {
7530
7546
if (isInProcess(source, target)) {
7531
7547
return;
7532
7548
}
7533
7549
if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) {
7534
7550
return;
7535
7551
}
7536
-
7537
7552
const key = source.id + "," + target.id;
7538
7553
if (hasProperty(visited, key)) {
7539
7554
return;
7540
7555
}
7541
7556
visited[key] = true;
7542
-
7543
7557
if (depth === 0) {
7544
7558
sourceStack = [];
7545
7559
targetStack = [];
0 commit comments