@@ -13489,7 +13489,7 @@ namespace ts {
13489
13489
13490
13490
function getRegularTypeOfLiteralType(type: Type): Type {
13491
13491
return type.flags & TypeFlags.Literal ? (<LiteralType>type).regularType :
13492
- type.flags & TypeFlags.Union ? getUnionType(sameMap((<UnionType>type).types, getRegularTypeOfLiteralType)) :
13492
+ type.flags & TypeFlags.Union ? ((<UnionType>type).regularType || ((<UnionType>type).regularType = getUnionType(sameMap((<UnionType>type).types, getRegularTypeOfLiteralType)) as UnionType )) :
13493
13493
type;
13494
13494
}
13495
13495
@@ -15487,6 +15487,16 @@ namespace ts {
15487
15487
return isIdenticalTo(source, target);
15488
15488
}
15489
15489
15490
+
15491
+ // We fastpath comparing a type parameter to exactly its constraint, as this is _super_ common,
15492
+ // and otherwise, for type parameters in large unions, causes us to need to compare the union to itself,
15493
+ // as we break down the _target_ union first, _then_ get the source constraint - so for every
15494
+ // member of the target, we attempt to find a match in the source. This avoids that in cases where
15495
+ // the target is exactly the constraint.
15496
+ if (source.flags & TypeFlags.TypeParameter && getConstraintOfType(source) === target) {
15497
+ return Ternary.True;
15498
+ }
15499
+
15490
15500
// Try to see if we're relating something like `Foo` -> `Bar | null | undefined`.
15491
15501
// If so, reporting the `null` and `undefined` in the type is hardly useful.
15492
15502
// First, see if we're even relating an object type to a union.
@@ -15820,7 +15830,16 @@ namespace ts {
15820
15830
function eachTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary {
15821
15831
let result = Ternary.True;
15822
15832
const sourceTypes = source.types;
15823
- for (const sourceType of sourceTypes) {
15833
+ for (let i = 0; i < sourceTypes.length; i++) {
15834
+ const sourceType = sourceTypes[i];
15835
+ if (target.flags & TypeFlags.Union && (target as UnionType).types.length === sourceTypes.length) {
15836
+ // many unions are mappings of one another; in such cases, simply comparing members at the same index can shortcut the comparison
15837
+ const related = isRelatedTo(sourceType, (target as UnionType).types[i], /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState);
15838
+ if (related) {
15839
+ result &= related;
15840
+ continue;
15841
+ }
15842
+ }
15824
15843
const related = isRelatedTo(sourceType, target, reportErrors, /*headMessage*/ undefined, intersectionState);
15825
15844
if (!related) {
15826
15845
return Ternary.False;
0 commit comments