@@ -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