Skip to content

Commit 2f15741

Browse files
committed
Add reduceType
1 parent b897272 commit 2f15741

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

Comments
 (0)