mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-07-04 14:56:16 -05:00
Allow infer type variables to have constraints inferred (#32093)
* Allow `infer` type variables to have constraints infered and allow the breakdown of substitutes in simplifiable source inferences * Still skip conditional inference when `extends infer Q` so such a pattern still acts as a constraint size breaker
This commit is contained in:
@@ -12342,6 +12342,13 @@ namespace ts {
|
||||
}
|
||||
}
|
||||
|
||||
function unwrapSubstitution(type: Type): Type {
|
||||
if (type.flags & TypeFlags.Substitution) {
|
||||
return (type as SubstitutionType).substitute;
|
||||
}
|
||||
return type;
|
||||
}
|
||||
|
||||
// Transform an indexed access to a simpler form, if possible. Return the simpler form, or return
|
||||
// the type itself if no transformation is possible. The writing flag indicates that the type is
|
||||
// the target of an assignment.
|
||||
@@ -12353,7 +12360,7 @@ namespace ts {
|
||||
type[cache] = circularConstraintType;
|
||||
// We recursively simplify the object type as it may in turn be an indexed access type. For example, with
|
||||
// '{ [P in T]: { [Q in U]: number } }[T][U]' we want to first simplify the inner indexed access type.
|
||||
const objectType = getSimplifiedType(type.objectType, writing);
|
||||
const objectType = unwrapSubstitution(getSimplifiedType(type.objectType, writing));
|
||||
const indexType = getSimplifiedType(type.indexType, writing);
|
||||
// T[A | B] -> T[A] | T[B] (reading)
|
||||
// T[A | B] -> T[A] & T[B] (writing)
|
||||
@@ -12531,7 +12538,11 @@ namespace ts {
|
||||
let combinedMapper: TypeMapper | undefined;
|
||||
if (root.inferTypeParameters) {
|
||||
const context = createInferenceContext(root.inferTypeParameters, /*signature*/ undefined, InferenceFlags.None);
|
||||
if (!checkTypeInstantiable) {
|
||||
// We skip inference of the possible `infer` types unles the `extendsType` _is_ an infer type
|
||||
// if it was, it's trivial to say that extendsType = checkType, however such a pattern is used to
|
||||
// "reset" the type being build up during constraint calculation and avoid making an apparently "infinite" constraint
|
||||
// so in those cases we refain from performing inference and retain the uninfered type parameter
|
||||
if (!checkTypeInstantiable || !some(root.inferTypeParameters, t => t === extendsType)) {
|
||||
// We don't want inferences from constraints as they may cause us to eagerly resolve the
|
||||
// conditional type instead of deferring resolution. Also, we always want strict function
|
||||
// types rules (i.e. proper contravariance) for inferences.
|
||||
@@ -17863,6 +17874,12 @@ namespace ts {
|
||||
invokeOnce(source, target, inferFromObjectTypes);
|
||||
}
|
||||
}
|
||||
if (source.flags & TypeFlags.Simplifiable) {
|
||||
const simplified = getSimplifiedType(source, contravariant);
|
||||
if (simplified !== source) {
|
||||
inferFromTypes(simplified, target);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function inferWithPriority(source: Type, target: Type, newPriority: InferencePriority) {
|
||||
|
||||
Reference in New Issue
Block a user