mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-21 18:22:58 -05:00
Cache the regularized form of union types (#37749)
* Cache the regularized form of union types * Inline function because why not * Introduce two fastpasths into isRelatedTo
This commit is contained in:
@@ -13489,7 +13489,7 @@ namespace ts {
|
||||
|
||||
function getRegularTypeOfLiteralType(type: Type): Type {
|
||||
return type.flags & TypeFlags.Literal ? (<LiteralType>type).regularType :
|
||||
type.flags & TypeFlags.Union ? getUnionType(sameMap((<UnionType>type).types, getRegularTypeOfLiteralType)) :
|
||||
type.flags & TypeFlags.Union ? ((<UnionType>type).regularType || ((<UnionType>type).regularType = getUnionType(sameMap((<UnionType>type).types, getRegularTypeOfLiteralType)) as UnionType)) :
|
||||
type;
|
||||
}
|
||||
|
||||
@@ -15487,6 +15487,16 @@ namespace ts {
|
||||
return isIdenticalTo(source, target);
|
||||
}
|
||||
|
||||
|
||||
// We fastpath comparing a type parameter to exactly its constraint, as this is _super_ common,
|
||||
// and otherwise, for type parameters in large unions, causes us to need to compare the union to itself,
|
||||
// as we break down the _target_ union first, _then_ get the source constraint - so for every
|
||||
// member of the target, we attempt to find a match in the source. This avoids that in cases where
|
||||
// the target is exactly the constraint.
|
||||
if (source.flags & TypeFlags.TypeParameter && getConstraintOfType(source) === target) {
|
||||
return Ternary.True;
|
||||
}
|
||||
|
||||
// Try to see if we're relating something like `Foo` -> `Bar | null | undefined`.
|
||||
// If so, reporting the `null` and `undefined` in the type is hardly useful.
|
||||
// First, see if we're even relating an object type to a union.
|
||||
@@ -15820,7 +15830,16 @@ namespace ts {
|
||||
function eachTypeRelatedToType(source: UnionOrIntersectionType, target: Type, reportErrors: boolean, intersectionState: IntersectionState): Ternary {
|
||||
let result = Ternary.True;
|
||||
const sourceTypes = source.types;
|
||||
for (const sourceType of sourceTypes) {
|
||||
for (let i = 0; i < sourceTypes.length; i++) {
|
||||
const sourceType = sourceTypes[i];
|
||||
if (target.flags & TypeFlags.Union && (target as UnionType).types.length === sourceTypes.length) {
|
||||
// many unions are mappings of one another; in such cases, simply comparing members at the same index can shortcut the comparison
|
||||
const related = isRelatedTo(sourceType, (target as UnionType).types[i], /*reportErrors*/ false, /*headMessage*/ undefined, intersectionState);
|
||||
if (related) {
|
||||
result &= related;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
const related = isRelatedTo(sourceType, target, reportErrors, /*headMessage*/ undefined, intersectionState);
|
||||
if (!related) {
|
||||
return Ternary.False;
|
||||
|
||||
@@ -4653,6 +4653,8 @@ namespace ts {
|
||||
export interface UnionType extends UnionOrIntersectionType {
|
||||
/* @internal */
|
||||
resolvedReducedType: Type;
|
||||
/* @internal */
|
||||
regularType: UnionType;
|
||||
}
|
||||
|
||||
export interface IntersectionType extends UnionOrIntersectionType {
|
||||
|
||||
Reference in New Issue
Block a user