mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-06-24 07:16:39 -05:00
Merge pull request #17382 from Microsoft/fixPartialTypeRelations
Fix partial type relations
This commit is contained in:
@@ -5787,12 +5787,13 @@ namespace ts {
|
||||
return type.modifiersType;
|
||||
}
|
||||
|
||||
function isPartialMappedType(type: Type) {
|
||||
return getObjectFlags(type) & ObjectFlags.Mapped && !!(<MappedType>type).declaration.questionToken;
|
||||
}
|
||||
|
||||
function isGenericMappedType(type: Type) {
|
||||
if (getObjectFlags(type) & ObjectFlags.Mapped) {
|
||||
const constraintType = getConstraintTypeFromMappedType(<MappedType>type);
|
||||
return maybeTypeOfKind(constraintType, TypeFlags.TypeVariable | TypeFlags.Index);
|
||||
}
|
||||
return false;
|
||||
return getObjectFlags(type) & ObjectFlags.Mapped &&
|
||||
maybeTypeOfKind(getConstraintTypeFromMappedType(<MappedType>type), TypeFlags.TypeVariable | TypeFlags.Index);
|
||||
}
|
||||
|
||||
function resolveStructuredTypeMembers(type: StructuredType): ResolvedType {
|
||||
@@ -9280,8 +9281,12 @@ namespace ts {
|
||||
if (source.flags & (TypeFlags.Object | TypeFlags.Intersection) && target.flags & TypeFlags.Object) {
|
||||
// Report structural errors only if we haven't reported any errors yet
|
||||
const reportStructuralErrors = reportErrors && errorInfo === saveErrorInfo && !sourceIsPrimitive;
|
||||
if (isGenericMappedType(source) || isGenericMappedType(target)) {
|
||||
result = mappedTypeRelatedTo(source, target, reportStructuralErrors);
|
||||
// An empty object type is related to any mapped type that includes a '?' modifier.
|
||||
if (isPartialMappedType(target) && !isGenericMappedType(source) && isEmptyObjectType(source)) {
|
||||
result = Ternary.True;
|
||||
}
|
||||
else if (isGenericMappedType(target)) {
|
||||
result = isGenericMappedType(source) ? mappedTypeRelatedTo(<MappedType>source, <MappedType>target, reportStructuralErrors) : Ternary.False;
|
||||
}
|
||||
else {
|
||||
result = propertiesRelatedTo(source, target, reportStructuralErrors);
|
||||
@@ -9310,33 +9315,19 @@ namespace ts {
|
||||
// A type [P in S]: X is related to a type [Q in T]: Y if T is related to S and X' is
|
||||
// related to Y, where X' is an instantiation of X in which P is replaced with Q. Notice
|
||||
// that S and T are contra-variant whereas X and Y are co-variant.
|
||||
function mappedTypeRelatedTo(source: Type, target: Type, reportErrors: boolean): Ternary {
|
||||
if (isGenericMappedType(target)) {
|
||||
if (isGenericMappedType(source)) {
|
||||
const sourceReadonly = !!(<MappedType>source).declaration.readonlyToken;
|
||||
const sourceOptional = !!(<MappedType>source).declaration.questionToken;
|
||||
const targetReadonly = !!(<MappedType>target).declaration.readonlyToken;
|
||||
const targetOptional = !!(<MappedType>target).declaration.questionToken;
|
||||
const modifiersRelated = relation === identityRelation ?
|
||||
sourceReadonly === targetReadonly && sourceOptional === targetOptional :
|
||||
relation === comparableRelation || !sourceOptional || targetOptional;
|
||||
if (modifiersRelated) {
|
||||
let result: Ternary;
|
||||
if (result = isRelatedTo(getConstraintTypeFromMappedType(<MappedType>target), getConstraintTypeFromMappedType(<MappedType>source), reportErrors)) {
|
||||
const mapper = createTypeMapper([getTypeParameterFromMappedType(<MappedType>source)], [getTypeParameterFromMappedType(<MappedType>target)]);
|
||||
return result & isRelatedTo(instantiateType(getTemplateTypeFromMappedType(<MappedType>source), mapper), getTemplateTypeFromMappedType(<MappedType>target), reportErrors);
|
||||
}
|
||||
}
|
||||
}
|
||||
else if ((<MappedType>target).declaration.questionToken && isEmptyObjectType(source)) {
|
||||
return Ternary.True;
|
||||
|
||||
}
|
||||
}
|
||||
else if (relation !== identityRelation) {
|
||||
const resolved = resolveStructuredTypeMembers(<ObjectType>target);
|
||||
if (isEmptyResolvedType(resolved) || resolved.stringIndexInfo && resolved.stringIndexInfo.type.flags & TypeFlags.Any) {
|
||||
return Ternary.True;
|
||||
function mappedTypeRelatedTo(source: MappedType, target: MappedType, reportErrors: boolean): Ternary {
|
||||
const sourceReadonly = !!source.declaration.readonlyToken;
|
||||
const sourceOptional = !!source.declaration.questionToken;
|
||||
const targetReadonly = !!target.declaration.readonlyToken;
|
||||
const targetOptional = !!target.declaration.questionToken;
|
||||
const modifiersRelated = relation === identityRelation ?
|
||||
sourceReadonly === targetReadonly && sourceOptional === targetOptional :
|
||||
relation === comparableRelation || !sourceOptional || targetOptional;
|
||||
if (modifiersRelated) {
|
||||
let result: Ternary;
|
||||
if (result = isRelatedTo(getConstraintTypeFromMappedType(<MappedType>target), getConstraintTypeFromMappedType(<MappedType>source), reportErrors)) {
|
||||
const mapper = createTypeMapper([getTypeParameterFromMappedType(<MappedType>source)], [getTypeParameterFromMappedType(<MappedType>target)]);
|
||||
return result & isRelatedTo(instantiateType(getTemplateTypeFromMappedType(<MappedType>source), mapper), getTemplateTypeFromMappedType(<MappedType>target), reportErrors);
|
||||
}
|
||||
}
|
||||
return Ternary.False;
|
||||
|
||||
Reference in New Issue
Block a user