@@ -22777,8 +22777,7 @@ namespace ts {
22777
22777
const inferenceContext = getInferenceInfoForType(target);
22778
22778
const constraint = inferenceContext ? getBaseConstraintOfType(inferenceContext.typeParameter) : undefined;
22779
22779
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);
22782
22781
22783
22782
// If the constraint contains `string`, we don't need to look for a more preferred type
22784
22783
if (!(allTypeFlags & TypeFlags.String)) {
@@ -22788,38 +22787,27 @@ namespace ts {
22788
22787
if (allTypeFlags & TypeFlags.NumberLike && !isValidNumberString(str, /*roundTripOnly*/ true)) {
22789
22788
allTypeFlags &= ~TypeFlags.NumberLike;
22790
22789
}
22791
-
22790
+
22792
22791
// If the type contains `bigint` or a bigint literal and the string isn't a valid bigint, exclude bigints
22793
22792
if (allTypeFlags & TypeFlags.BigIntLike && !isValidBigIntString(str, /*roundTripOnly*/ true)) {
22794
22793
allTypeFlags &= ~TypeFlags.BigIntLike;
22795
22794
}
22796
-
22795
+
22797
22796
// 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)) {
22823
22811
inferFromTypes(matchingType, target);
22824
22812
continue;
22825
22813
}
@@ -23835,6 +23823,12 @@ namespace ts {
23835
23823
return type.flags & TypeFlags.Union ? forEach((type as UnionType).types, f) : f(type);
23836
23824
}
23837
23825
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
+
23838
23832
function someType(type: Type, f: (t: Type) => boolean): boolean {
23839
23833
return type.flags & TypeFlags.Union ? some((type as UnionType).types, f) : f(type);
23840
23834
}
0 commit comments