mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-02-09 12:15:34 -06:00
Improve type relationships for generic mapped types
This commit is contained in:
parent
04da7074f9
commit
bf7258742e
@ -4662,10 +4662,6 @@ namespace ts {
|
||||
return type.modifiersType;
|
||||
}
|
||||
|
||||
function getErasedTemplateTypeFromMappedType(type: MappedType) {
|
||||
return instantiateType(getTemplateTypeFromMappedType(type), createTypeEraser([getTypeParameterFromMappedType(type)]));
|
||||
}
|
||||
|
||||
function isGenericMappedType(type: Type) {
|
||||
if (getObjectFlags(type) & ObjectFlags.Mapped) {
|
||||
const constraintType = getConstraintTypeFromMappedType(<MappedType>type);
|
||||
@ -7765,25 +7761,24 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
// A type [P in S]: X is related to a type [P in T]: Y if T is related to S and X is related to Y.
|
||||
// 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)) {
|
||||
let result: Ternary;
|
||||
if (relation === identityRelation) {
|
||||
const readonlyMatches = !(<MappedType>source).declaration.readonlyToken === !(<MappedType>target).declaration.readonlyToken;
|
||||
const optionalMatches = !(<MappedType>source).declaration.questionToken === !(<MappedType>target).declaration.questionToken;
|
||||
if (readonlyMatches && optionalMatches) {
|
||||
if (result = isRelatedTo(getConstraintTypeFromMappedType(<MappedType>target), getConstraintTypeFromMappedType(<MappedType>source), reportErrors)) {
|
||||
return result & isRelatedTo(getErasedTemplateTypeFromMappedType(<MappedType>source), getErasedTemplateTypeFromMappedType(<MappedType>target), reportErrors);
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
if (relation === comparableRelation || !(<MappedType>source).declaration.questionToken || (<MappedType>target).declaration.questionToken) {
|
||||
if (result = isRelatedTo(getConstraintTypeFromMappedType(<MappedType>target), getConstraintTypeFromMappedType(<MappedType>source), reportErrors)) {
|
||||
return result & isRelatedTo(getTemplateTypeFromMappedType(<MappedType>source), getTemplateTypeFromMappedType(<MappedType>target), reportErrors);
|
||||
}
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user