Skip to content

Commit 0a16032

Browse files
authored
Faster exit from isTypeRelatedTo with identityRelation (#36590)
* Faster exit from isTypeRelatedTo with identityRelation * Reorganize a bit
1 parent 77b81ed commit 0a16032

File tree

2 files changed

+27
-20
lines changed

2 files changed

+27
-20
lines changed

src/compiler/checker.ts

Lines changed: 25 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -14706,11 +14706,17 @@ namespace ts {
1470614706
if (isFreshLiteralType(target)) {
1470714707
target = (<FreshableType>target).regularType;
1470814708
}
14709-
if (source === target ||
14710-
relation === comparableRelation && !(target.flags & TypeFlags.Never) && isSimpleTypeRelatedTo(target, source, relation) ||
14711-
relation !== identityRelation && isSimpleTypeRelatedTo(source, target, relation)) {
14709+
if (source === target) {
1471214710
return true;
1471314711
}
14712+
if (relation !== identityRelation) {
14713+
if (relation === comparableRelation && !(target.flags & TypeFlags.Never) && isSimpleTypeRelatedTo(target, source, relation) || isSimpleTypeRelatedTo(source, target, relation)) {
14714+
return true;
14715+
}
14716+
}
14717+
else {
14718+
if (!(source.flags === target.flags && source.flags & TypeFlags.Substructure)) return false;
14719+
}
1471414720
if (source.flags & TypeFlags.Object && target.flags & TypeFlags.Object) {
1471514721
const related = relation.get(getRelationKey(source, target, IntersectionState.None, relation));
1471614722
if (related !== undefined) {
@@ -15048,6 +15054,12 @@ namespace ts {
1504815054
let source = getNormalizedType(originalSource, /*writing*/ false);
1504915055
let target = getNormalizedType(originalTarget, /*writing*/ true);
1505015056

15057+
if (source === target) return Ternary.True;
15058+
15059+
if (relation === identityRelation) {
15060+
return isIdenticalTo(source, target);
15061+
}
15062+
1505115063
// Try to see if we're relating something like `Foo` -> `Bar | null | undefined`.
1505215064
// If so, reporting the `null` and `undefined` in the type is hardly useful.
1505315065
// First, see if we're even relating an object type to a union.
@@ -15061,17 +15073,11 @@ namespace ts {
1506115073
(target as UnionType).types.length <= 3 && maybeTypeOfKind(target, TypeFlags.Nullable)) {
1506215074
const nullStrippedTarget = extractTypesOfKind(target, ~TypeFlags.Nullable);
1506315075
if (!(nullStrippedTarget.flags & (TypeFlags.Union | TypeFlags.Never))) {
15076+
if (source === nullStrippedTarget) return Ternary.True;
1506415077
target = nullStrippedTarget;
1506515078
}
1506615079
}
1506715080

15068-
// both types are the same - covers 'they are the same primitive type or both are Any' or the same type parameter cases
15069-
if (source === target) return Ternary.True;
15070-
15071-
if (relation === identityRelation) {
15072-
return isIdenticalTo(source, target);
15073-
}
15074-
1507515081
if (relation === comparableRelation && !(target.flags & TypeFlags.Never) && isSimpleTypeRelatedTo(target, source, relation) ||
1507615082
isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) return Ternary.True;
1507715083

@@ -15217,19 +15223,18 @@ namespace ts {
1521715223
}
1521815224

1521915225
function isIdenticalTo(source: Type, target: Type): Ternary {
15220-
let result: Ternary;
1522115226
const flags = source.flags & target.flags;
15222-
if (flags & TypeFlags.Object || flags & TypeFlags.IndexedAccess || flags & TypeFlags.Conditional || flags & TypeFlags.Index || flags & TypeFlags.Substitution) {
15223-
return recursiveTypeRelatedTo(source, target, /*reportErrors*/ false, IntersectionState.None);
15227+
if (!(flags & TypeFlags.Substructure)) {
15228+
return Ternary.False;
1522415229
}
15225-
if (flags & (TypeFlags.Union | TypeFlags.Intersection)) {
15226-
if (result = eachTypeRelatedToSomeType(<UnionOrIntersectionType>source, <UnionOrIntersectionType>target)) {
15227-
if (result &= eachTypeRelatedToSomeType(<UnionOrIntersectionType>target, <UnionOrIntersectionType>source)) {
15228-
return result;
15229-
}
15230+
if (flags & TypeFlags.UnionOrIntersection) {
15231+
let result = eachTypeRelatedToSomeType(<UnionOrIntersectionType>source, <UnionOrIntersectionType>target);
15232+
if (result) {
15233+
result &= eachTypeRelatedToSomeType(<UnionOrIntersectionType>target, <UnionOrIntersectionType>source);
1523015234
}
15235+
return result;
1523115236
}
15232-
return Ternary.False;
15237+
return recursiveTypeRelatedTo(source, target, /*reportErrors*/ false, IntersectionState.None);
1523315238
}
1523415239

1523515240
function getTypeOfPropertyInTypes(types: Type[], name: __String) {
@@ -18390,7 +18395,7 @@ namespace ts {
1839018395
}
1839118396

1839218397
function isTypeOrBaseIdenticalTo(s: Type, t: Type) {
18393-
return isTypeIdenticalTo(s, t) || !!(s.flags & (TypeFlags.StringLiteral | TypeFlags.NumberLiteral)) && isTypeIdenticalTo(getBaseTypeOfLiteralType(s), t);
18398+
return isTypeIdenticalTo(s, t) || !!(t.flags & TypeFlags.String && s.flags & TypeFlags.StringLiteral || t.flags & TypeFlags.Number && s.flags & TypeFlags.NumberLiteral);
1839418399
}
1839518400

1839618401
function isTypeCloselyMatchedBy(s: Type, t: Type) {

src/compiler/types.ts

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4328,6 +4328,8 @@ namespace ts {
43284328
ObjectFlagsType = Any | Nullable | Never | Object | Union | Intersection,
43294329
/* @internal */
43304330
Simplifiable = IndexedAccess | Conditional,
4331+
/* @internal */
4332+
Substructure = Object | Union | Intersection | Index | IndexedAccess | Conditional | Substitution,
43314333
// 'Narrowable' types are types where narrowing actually narrows.
43324334
// This *should* be every type other than null, undefined, void, and never
43334335
Narrowable = Any | Unknown | StructuredOrInstantiable | StringLike | NumberLike | BigIntLike | BooleanLike | ESSymbol | UniqueESSymbol | NonPrimitive,

0 commit comments

Comments
 (0)