Skip to content

Commit a1a8725

Browse files
committed
Optimize type inference
1 parent ff0cbb5 commit a1a8725

File tree

2 files changed

+24
-10
lines changed

2 files changed

+24
-10
lines changed

Diff for: src/compiler/checker.ts

+22-8
Original file line numberDiff line numberDiff line change
@@ -7393,6 +7393,24 @@ namespace ts {
73937393
};
73947394
}
73957395

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+
73967414
function inferTypes(context: InferenceContext, source: Type, target: Type) {
73977415
let sourceStack: Type[];
73987416
let targetStack: Type[];
@@ -7411,6 +7429,9 @@ namespace ts {
74117429
}
74127430

74137431
function inferFromTypes(source: Type, target: Type) {
7432+
if (!couldContainTypeParameters(target)) {
7433+
return;
7434+
}
74147435
if (source.flags & TypeFlags.Union && target.flags & TypeFlags.Union && !(source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum) ||
74157436
source.flags & TypeFlags.Intersection && target.flags & TypeFlags.Intersection) {
74167437
// Source and target are both unions or both intersections. If source and target
@@ -7521,25 +7542,18 @@ namespace ts {
75217542
}
75227543
else {
75237544
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) {
75307546
if (isInProcess(source, target)) {
75317547
return;
75327548
}
75337549
if (isDeeplyNestedGeneric(source, sourceStack, depth) && isDeeplyNestedGeneric(target, targetStack, depth)) {
75347550
return;
75357551
}
7536-
75377552
const key = source.id + "," + target.id;
75387553
if (hasProperty(visited, key)) {
75397554
return;
75407555
}
75417556
visited[key] = true;
7542-
75437557
if (depth === 0) {
75447558
sourceStack = [];
75457559
targetStack = [];

Diff for: src/compiler/types.ts

+2-2
Original file line numberDiff line numberDiff line change
@@ -2364,9 +2364,9 @@ namespace ts {
23642364
export interface UnionOrIntersectionType extends Type {
23652365
types: Type[]; // Constituent types
23662366
/* @internal */
2367-
reducedType: Type; // Reduced union type (all subtypes removed)
2368-
/* @internal */
23692367
resolvedProperties: SymbolTable; // Cache of resolved properties
2368+
/* @internal */
2369+
couldContainTypeParameters: boolean;
23702370
}
23712371

23722372
export interface UnionType extends UnionOrIntersectionType { }

0 commit comments

Comments
 (0)