@@ -22777,8 +22777,7 @@ namespace ts {
2277722777 const inferenceContext = getInferenceInfoForType(target);
2277822778 const constraint = inferenceContext ? getBaseConstraintOfType(inferenceContext.typeParameter) : undefined;
2277922779 if (constraint && !isTypeAny(constraint)) {
22780- let allTypeFlags: TypeFlags = 0;
22781- forEachType(constraint, t => { allTypeFlags |= t.flags; });
22780+ let allTypeFlags = reduceType(constraint, (flags, t) => flags | t.flags, 0 as TypeFlags);
2278222781
2278322782 // If the constraint contains `string`, we don't need to look for a more preferred type
2278422783 if (!(allTypeFlags & TypeFlags.String)) {
@@ -22788,38 +22787,27 @@ namespace ts {
2278822787 if (allTypeFlags & TypeFlags.NumberLike && !isValidNumberString(str, /*roundTripOnly*/ true)) {
2278922788 allTypeFlags &= ~TypeFlags.NumberLike;
2279022789 }
22791-
22790+
2279222791 // If the type contains `bigint` or a bigint literal and the string isn't a valid bigint, exclude bigints
2279322792 if (allTypeFlags & TypeFlags.BigIntLike && !isValidBigIntString(str, /*roundTripOnly*/ true)) {
2279422793 allTypeFlags &= ~TypeFlags.BigIntLike;
2279522794 }
22796-
22795+
2279722796 // for each type in the constraint, find the highest priority matching type
22798- let matchingType: Type | undefined;
22799- let matchingTypePriority = TemplateTypePlaceholderPriority.Never;
22800- forEachType(constraint, t => {
22801- if (t.flags & allTypeFlags) {
22802- const typePriority = getTemplateTypePlaceholderPriority(t);
22803- if (typePriority > matchingTypePriority) {
22804- const newMatchingType =
22805- t.flags & TypeFlags.String ? source :
22806- t.flags & TypeFlags.Number ? getNumberLiteralType(+str) : // if `str` was not a valid number, TypeFlags.Number would have been excluded above.
22807- t.flags & TypeFlags.BigInt ? parseBigIntLiteralType(str) : // if `str` was not a valid bigint, TypeFlags.BigInt would have been excluded above.
22808- t.flags & TypeFlags.Boolean ? str === "true" ? trueType : falseType :
22809- t.flags & TypeFlags.StringLiteral && (t as StringLiteralType).value === str ? t :
22810- t.flags & TypeFlags.NumberLiteral && (t as NumberLiteralType).value === +str ? t :
22811- t.flags & TypeFlags.BigIntLiteral && pseudoBigIntToString((t as BigIntLiteralType).value) === str ? t :
22812- t.flags & (TypeFlags.BooleanLiteral | TypeFlags.Nullable) && (t as IntrinsicType).intrinsicName === str ? t :
22813- undefined;
22814- if (newMatchingType) {
22815- matchingType = newMatchingType;
22816- matchingTypePriority = typePriority;
22817- }
22818- }
22819- }
22820- });
22821-
22822- if (matchingType) {
22797+ const matchingType = reduceType(constraint, (matchingType, t) =>
22798+ !(t.flags & allTypeFlags) || getTemplateTypePlaceholderPriority(t) <= getTemplateTypePlaceholderPriority(matchingType) ? matchingType :
22799+ t.flags & TypeFlags.String ? source :
22800+ t.flags & TypeFlags.Number ? getNumberLiteralType(+str) : // if `str` was not a valid number, TypeFlags.Number would have been excluded above.
22801+ t.flags & TypeFlags.BigInt ? parseBigIntLiteralType(str) : // if `str` was not a valid bigint, TypeFlags.BigInt would have been excluded above.
22802+ t.flags & TypeFlags.Boolean ? str === "true" ? trueType : falseType :
22803+ t.flags & TypeFlags.StringLiteral && (t as StringLiteralType).value === str ? t :
22804+ t.flags & TypeFlags.NumberLiteral && (t as NumberLiteralType).value === +str ? t :
22805+ t.flags & TypeFlags.BigIntLiteral && pseudoBigIntToString((t as BigIntLiteralType).value) === str ? t :
22806+ t.flags & (TypeFlags.BooleanLiteral | TypeFlags.Nullable) && (t as IntrinsicType).intrinsicName === str ? t :
22807+ matchingType,
22808+ neverType as Type);
22809+
22810+ if (!(matchingType.flags & TypeFlags.Never)) {
2282322811 inferFromTypes(matchingType, target);
2282422812 continue;
2282522813 }
@@ -23835,6 +23823,12 @@ namespace ts {
2383523823 return type.flags & TypeFlags.Union ? forEach((type as UnionType).types, f) : f(type);
2383623824 }
2383723825
23826+ function reduceType<T>(type: Type, f: (memo: T, t: Type) => T | undefined, initial: T): T;
23827+ function reduceType<T>(type: Type, f: (memo: T | undefined, t: Type) => T | undefined): T | undefined;
23828+ function reduceType<T>(type: Type, f: (memo: T | undefined, t: Type) => T | undefined, initial?: T | undefined): T | undefined {
23829+ return type.flags & TypeFlags.Union ? reduceLeft((type as UnionType).types, f, initial) : f(initial, type);
23830+ }
23831+
2383823832 function someType(type: Type, f: (t: Type) => boolean): boolean {
2383923833 return type.flags & TypeFlags.Union ? some((type as UnionType).types, f) : f(type);
2384023834 }
0 commit comments