mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-18 07:29:16 -05:00
Merge pull request #29787 from Microsoft/inferToPartiallyHomomorphic
Infer to partially homomorphic types (such as Pick<T, K>)
This commit is contained in:
@@ -14580,11 +14580,11 @@ namespace ts {
|
||||
return undefined;
|
||||
}
|
||||
|
||||
function inferFromMappedTypeConstraint(source: Type, target: Type, constraintType: Type): boolean {
|
||||
function inferToMappedType(source: Type, target: MappedType, constraintType: Type): boolean {
|
||||
if (constraintType.flags & TypeFlags.Union) {
|
||||
let result = false;
|
||||
for (const type of (constraintType as UnionType).types) {
|
||||
result = inferFromMappedTypeConstraint(source, target, type) || result;
|
||||
result = inferToMappedType(source, target, type) || result;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
@@ -14595,7 +14595,7 @@ namespace ts {
|
||||
// such that direct inferences to T get priority over inferences to Partial<T>, for example.
|
||||
const inference = getInferenceInfoForType((<IndexType>constraintType).type);
|
||||
if (inference && !inference.isFixed) {
|
||||
const inferredType = inferTypeForHomomorphicMappedType(source, <MappedType>target, constraintType as IndexType);
|
||||
const inferredType = inferTypeForHomomorphicMappedType(source, target, <IndexType>constraintType);
|
||||
if (inferredType) {
|
||||
const savePriority = priority;
|
||||
priority |= InferencePriority.HomomorphicMappedType;
|
||||
@@ -14606,18 +14606,28 @@ namespace ts {
|
||||
return true;
|
||||
}
|
||||
if (constraintType.flags & TypeFlags.TypeParameter) {
|
||||
// We're inferring from some source type S to a mapped type { [P in T]: X }, where T is a type
|
||||
// parameter. Infer from 'keyof S' to T and infer from a union of each property type in S to X.
|
||||
// We're inferring from some source type S to a mapped type { [P in K]: X }, where K is a type
|
||||
// parameter. First infer from 'keyof S' to K.
|
||||
const savePriority = priority;
|
||||
priority |= InferencePriority.MappedTypeConstraint;
|
||||
inferFromTypes(getIndexType(source), constraintType);
|
||||
priority = savePriority;
|
||||
// If K is constrained to a type C, also infer to C. Thus, for a mapped type { [P in K]: X },
|
||||
// where K extends keyof T, we make the same inferences as for a homomorphic mapped type
|
||||
// { [P in keyof T]: X }. This enables us to make meaningful inferences when the target is a
|
||||
// Pick<T, K>.
|
||||
const extendedConstraint = getConstraintOfType(constraintType);
|
||||
if (extendedConstraint && inferToMappedType(source, target, extendedConstraint)) {
|
||||
return true;
|
||||
}
|
||||
// If no inferences can be made to K's constraint, infer from a union of the property types
|
||||
// in the source to the template type X.
|
||||
const valueTypes = compact([
|
||||
getIndexTypeOfType(source, IndexKind.String),
|
||||
getIndexTypeOfType(source, IndexKind.Number),
|
||||
...map(getPropertiesOfType(source), getTypeOfSymbol)
|
||||
]);
|
||||
inferFromTypes(getUnionType(valueTypes), getTemplateTypeFromMappedType(<MappedType>target));
|
||||
inferFromTypes(getUnionType(valueTypes), getTemplateTypeFromMappedType(target));
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
@@ -14632,7 +14642,7 @@ namespace ts {
|
||||
}
|
||||
if (getObjectFlags(target) & ObjectFlags.Mapped) {
|
||||
const constraintType = getConstraintTypeFromMappedType(<MappedType>target);
|
||||
if (inferFromMappedTypeConstraint(source, target, constraintType)) {
|
||||
if (inferToMappedType(source, <MappedType>target, constraintType)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user