Skip to content

Commit f861417

Browse files
committed
Add reduceType
1 parent d544213 commit f861417

File tree

1 file changed

+23
-29
lines changed

1 file changed

+23
-29
lines changed

src/compiler/checker.ts

Lines changed: 23 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -22430,8 +22430,7 @@ namespace ts {
2243022430
const inferenceContext = getInferenceInfoForType(target);
2243122431
const constraint = inferenceContext ? getBaseConstraintOfType(inferenceContext.typeParameter) : undefined;
2243222432
if (constraint && !isTypeAny(constraint)) {
22433-
let allTypeFlags: TypeFlags = 0;
22434-
forEachType(constraint, t => { allTypeFlags |= t.flags; });
22433+
let allTypeFlags = reduceType(constraint, (flags, t) => flags | t.flags, 0 as TypeFlags);
2243522434

2243622435
// If the constraint contains `string`, we don't need to look for a more preferred type
2243722436
if (!(allTypeFlags & TypeFlags.String)) {
@@ -22441,38 +22440,27 @@ namespace ts {
2244122440
if (allTypeFlags & TypeFlags.NumberLike && !isValidNumberString(str, /*roundTripOnly*/ true)) {
2244222441
allTypeFlags &= ~TypeFlags.NumberLike;
2244322442
}
22444-
22443+
2244522444
// If the type contains `bigint` or a bigint literal and the string isn't a valid bigint, exclude bigints
2244622445
if (allTypeFlags & TypeFlags.BigIntLike && !isValidBigIntString(str, /*roundTripOnly*/ true)) {
2244722446
allTypeFlags &= ~TypeFlags.BigIntLike;
2244822447
}
22449-
22448+
2245022449
// for each type in the constraint, find the highest priority matching type
22451-
let matchingType: Type | undefined;
22452-
let matchingTypePriority = TemplateTypePlaceholderPriority.Never;
22453-
forEachType(constraint, t => {
22454-
if (t.flags & allTypeFlags) {
22455-
const typePriority = getTemplateTypePlaceholderPriority(t);
22456-
if (typePriority > matchingTypePriority) {
22457-
const newMatchingType =
22458-
t.flags & TypeFlags.String ? source :
22459-
t.flags & TypeFlags.Number ? getNumberLiteralType(+str) : // if `str` was not a valid number, TypeFlags.Number would have been excluded above.
22460-
t.flags & TypeFlags.BigInt ? parseBigIntLiteralType(str) : // if `str` was not a valid bigint, TypeFlags.BigInt would have been excluded above.
22461-
t.flags & TypeFlags.Boolean ? str === "true" ? trueType : falseType :
22462-
t.flags & TypeFlags.StringLiteral && (t as StringLiteralType).value === str ? t :
22463-
t.flags & TypeFlags.NumberLiteral && (t as NumberLiteralType).value === +str ? t :
22464-
t.flags & TypeFlags.BigIntLiteral && pseudoBigIntToString((t as BigIntLiteralType).value) === str ? t :
22465-
t.flags & (TypeFlags.BooleanLiteral | TypeFlags.Nullable) && (t as IntrinsicType).intrinsicName === str ? t :
22466-
undefined;
22467-
if (newMatchingType) {
22468-
matchingType = newMatchingType;
22469-
matchingTypePriority = typePriority;
22470-
}
22471-
}
22472-
}
22473-
});
22474-
22475-
if (matchingType) {
22450+
const matchingType = reduceType(constraint, (matchingType, t) =>
22451+
!(t.flags & allTypeFlags) || getTemplateTypePlaceholderPriority(t) <= getTemplateTypePlaceholderPriority(matchingType) ? matchingType :
22452+
t.flags & TypeFlags.String ? source :
22453+
t.flags & TypeFlags.Number ? getNumberLiteralType(+str) : // if `str` was not a valid number, TypeFlags.Number would have been excluded above.
22454+
t.flags & TypeFlags.BigInt ? parseBigIntLiteralType(str) : // if `str` was not a valid bigint, TypeFlags.BigInt would have been excluded above.
22455+
t.flags & TypeFlags.Boolean ? str === "true" ? trueType : falseType :
22456+
t.flags & TypeFlags.StringLiteral && (t as StringLiteralType).value === str ? t :
22457+
t.flags & TypeFlags.NumberLiteral && (t as NumberLiteralType).value === +str ? t :
22458+
t.flags & TypeFlags.BigIntLiteral && pseudoBigIntToString((t as BigIntLiteralType).value) === str ? t :
22459+
t.flags & (TypeFlags.BooleanLiteral | TypeFlags.Nullable) && (t as IntrinsicType).intrinsicName === str ? t :
22460+
matchingType,
22461+
neverType as Type);
22462+
22463+
if (!(matchingType.flags & TypeFlags.Never)) {
2247622464
inferFromTypes(matchingType, target);
2247722465
continue;
2247822466
}
@@ -23447,6 +23435,12 @@ namespace ts {
2344723435
return type.flags & TypeFlags.Union ? forEach((type as UnionType).types, f) : f(type);
2344823436
}
2344923437

23438+
function reduceType<T>(type: Type, f: (memo: T, t: Type) => T | undefined, initial: T): T;
23439+
function reduceType<T>(type: Type, f: (memo: T | undefined, t: Type) => T | undefined): T | undefined;
23440+
function reduceType<T>(type: Type, f: (memo: T | undefined, t: Type) => T | undefined, initial?: T | undefined): T | undefined {
23441+
return type.flags & TypeFlags.Union ? reduceLeft((type as UnionType).types, f, initial) : f(initial, type);
23442+
}
23443+
2345023444
function someType(type: Type, f: (t: Type) => boolean): boolean {
2345123445
return type.flags & TypeFlags.Union ? some((type as UnionType).types, f) : f(type);
2345223446
}

0 commit comments

Comments
 (0)