@@ -22430,8 +22430,7 @@ namespace ts {
22430
22430
const inferenceContext = getInferenceInfoForType(target);
22431
22431
const constraint = inferenceContext ? getBaseConstraintOfType(inferenceContext.typeParameter) : undefined;
22432
22432
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);
22435
22434
22436
22435
// If the constraint contains `string`, we don't need to look for a more preferred type
22437
22436
if (!(allTypeFlags & TypeFlags.String)) {
@@ -22441,38 +22440,27 @@ namespace ts {
22441
22440
if (allTypeFlags & TypeFlags.NumberLike && !isValidNumberString(str, /*roundTripOnly*/ true)) {
22442
22441
allTypeFlags &= ~TypeFlags.NumberLike;
22443
22442
}
22444
-
22443
+
22445
22444
// If the type contains `bigint` or a bigint literal and the string isn't a valid bigint, exclude bigints
22446
22445
if (allTypeFlags & TypeFlags.BigIntLike && !isValidBigIntString(str, /*roundTripOnly*/ true)) {
22447
22446
allTypeFlags &= ~TypeFlags.BigIntLike;
22448
22447
}
22449
-
22448
+
22450
22449
// 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)) {
22476
22464
inferFromTypes(matchingType, target);
22477
22465
continue;
22478
22466
}
@@ -23447,6 +23435,12 @@ namespace ts {
23447
23435
return type.flags & TypeFlags.Union ? forEach((type as UnionType).types, f) : f(type);
23448
23436
}
23449
23437
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
+
23450
23444
function someType(type: Type, f: (t: Type) => boolean): boolean {
23451
23445
return type.flags & TypeFlags.Union ? some((type as UnionType).types, f) : f(type);
23452
23446
}
0 commit comments