@@ -5832,14 +5832,16 @@ namespace ts {
58325832 return compareSignaturesRelated(source, target, ignoreReturnTypes, /*reportErrors*/ false, /*errorReporter*/ undefined, compareTypesAssignable) !== Ternary.False;
58335833 }
58345834
5835+ type ErrorReporter = (message: DiagnosticMessage, arg0?: string, arg1?: string) => void;
5836+
58355837 /**
58365838 * See signatureRelatedTo, compareSignaturesIdentical
58375839 */
58385840 function compareSignaturesRelated(source: Signature,
58395841 target: Signature,
58405842 ignoreReturnTypes: boolean,
58415843 reportErrors: boolean,
5842- errorReporter: (d: DiagnosticMessage, arg0?: string, arg1?: string) => void ,
5844+ errorReporter: ErrorReporter ,
58435845 compareTypes: (s: Type, t: Type, reportErrors?: boolean) => Ternary): Ternary {
58445846 // TODO (drosen): De-duplicate code between related functions.
58455847 if (source === target) {
@@ -5924,7 +5926,7 @@ namespace ts {
59245926 function compareTypePredicateRelatedTo(source: TypePredicate,
59255927 target: TypePredicate,
59265928 reportErrors: boolean,
5927- errorReporter: (d: DiagnosticMessage, arg0?: string, arg1?: string) => void ,
5929+ errorReporter: ErrorReporter ,
59285930 compareTypes: (s: Type, t: Type, reportErrors?: boolean) => Ternary): Ternary {
59295931 if (source.kind !== target.kind) {
59305932 if (reportErrors) {
@@ -5961,8 +5963,8 @@ namespace ts {
59615963 const sourceReturnType = getReturnTypeOfSignature(erasedSource);
59625964 const targetReturnType = getReturnTypeOfSignature(erasedTarget);
59635965 if (targetReturnType === voidType
5964- || checkTypeRelatedTo (targetReturnType, sourceReturnType, assignableRelation, /*errorNode*/ undefined )
5965- || checkTypeRelatedTo (sourceReturnType, targetReturnType, assignableRelation, /*errorNode*/ undefined )) {
5966+ || isTypeRelatedTo (targetReturnType, sourceReturnType, assignableRelation)
5967+ || isTypeRelatedTo (sourceReturnType, targetReturnType, assignableRelation)) {
59665968
59675969 return isSignatureAssignableTo(erasedSource, erasedTarget, /*ignoreReturnTypes*/ true);
59685970 }
@@ -5996,49 +5998,60 @@ namespace ts {
59965998 }
59975999 }
59986000
5999- function isPrimtiveTypeRelatedTo(source: Type, target: Type, relation: Map<RelationComparisonResult>) {
6000- if (target.flags & TypeFlags.Any || source.flags & TypeFlags.Never) return true;
6001- if (source.flags & TypeFlags.Undefined) {
6002- if (!strictNullChecks || target.flags & (TypeFlags.Undefined | TypeFlags.Void)) return true;
6001+ function isEnumTypeRelatedTo(source: Type, target: Type, errorReporter?: ErrorReporter) {
6002+ if (source.symbol.flags & SymbolFlags.EnumMember && source.symbol.parent === target.symbol) {
6003+ return true;
60036004 }
6004- if (source.flags & TypeFlags.Null ) {
6005- if (!strictNullChecks || target.flags & TypeFlags.Null) return true ;
6005+ if (source.symbol.name !== target.symbol.name || !(source.symbol. flags & SymbolFlags.RegularEnum) || !(target.symbol.flags & SymbolFlags.RegularEnum) ) {
6006+ return false ;
60066007 }
6007- if (source.flags & TypeFlags.NumberLike && target === numberType) return true;
6008- if (source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum && source.symbol.flags & SymbolFlags.EnumMember && source.symbol.parent === target.symbol) {
6009- return true;
6008+ const targetEnumType = getTypeOfSymbol(target.symbol);
6009+ for (const property of getPropertiesOfType(getTypeOfSymbol(source.symbol))) {
6010+ if (property.flags & SymbolFlags.EnumMember) {
6011+ const targetProperty = getPropertyOfType(targetEnumType, property.name);
6012+ if (!targetProperty || !(targetProperty.flags & SymbolFlags.EnumMember)) {
6013+ if (errorReporter) {
6014+ errorReporter(Diagnostics.Property_0_is_missing_in_type_1, property.name,
6015+ typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType));
6016+ }
6017+ return false;
6018+ }
6019+ }
60106020 }
6011- if (source.flags & TypeFlags.StringLike && target === stringType) return true;
6021+ return true;
6022+ }
6023+
6024+ function isSimpleTypeRelatedTo(source: Type, target: Type, relation: Map<RelationComparisonResult>, errorReporter?: ErrorReporter) {
6025+ if (target.flags & TypeFlags.Never) return false;
6026+ if (target.flags & TypeFlags.Any || source.flags & TypeFlags.Never) return true;
6027+ if (source.flags & TypeFlags.StringLike && target.flags & TypeFlags.String) return true;
6028+ if (source.flags & TypeFlags.NumberLike && target.flags & TypeFlags.Number) return true;
6029+ if (source.flags & TypeFlags.BooleanLike && target.flags & TypeFlags.Boolean) return true;
6030+ if (source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum && isEnumTypeRelatedTo(source, target, errorReporter)) return true;
6031+ if (source.flags & TypeFlags.Undefined && (!strictNullChecks || target.flags & (TypeFlags.Undefined | TypeFlags.Void))) return true;
6032+ if (source.flags & TypeFlags.Null && (!strictNullChecks || target.flags & TypeFlags.Null)) return true;
60126033 if (relation === assignableRelation || relation === comparableRelation) {
60136034 if (source.flags & TypeFlags.Any) return true;
6014- if (source === numberType && target.flags & TypeFlags.Enum) return true;
6035+ if (source.flags & TypeFlags.Number && target.flags & TypeFlags.Enum) return true;
60156036 }
6016- if (source.flags & TypeFlags.BooleanLike && target.flags & TypeFlags.Boolean) return true;
60176037 return false;
60186038 }
60196039
60206040 function isTypeRelatedTo(source: Type, target: Type, relation: Map<RelationComparisonResult>) {
6021- if (source === target) {
6041+ if (source === target || relation !== identityRelation && isSimpleTypeRelatedTo(source, target, relation) ) {
60226042 return true;
60236043 }
6024- if (relation !== identityRelation) {
6025- if (source.flags & TypeFlags.Primitive && target.flags & TypeFlags.Primitive) {
6026- if (isPrimtiveTypeRelatedTo(source, target, relation)) {
6027- return true;
6028- }
6029- if (!(source.flags & TypeFlags.Union || target.flags & TypeFlags.Union)) {
6030- return false;
6031- }
6032- }
6033- }
60346044 if (source.flags & TypeFlags.ObjectType && target.flags & TypeFlags.ObjectType) {
60356045 const id = relation !== identityRelation || source.id < target.id ? source.id + "," + target.id : target.id + "," + source.id;
60366046 const related = relation[id];
60376047 if (related !== undefined) {
60386048 return related === RelationComparisonResult.Succeeded;
60396049 }
60406050 }
6041- return checkTypeRelatedTo(source, target, relation, undefined, undefined, undefined);
6051+ if (source.flags & TypeFlags.StructuredOrTypeParameter || target.flags & TypeFlags.StructuredOrTypeParameter) {
6052+ return checkTypeRelatedTo(source, target, relation, undefined, undefined, undefined);
6053+ }
6054+ return false;
60426055 }
60436056
60446057 /**
@@ -6112,33 +6125,12 @@ namespace ts {
61126125 let result: Ternary;
61136126 // both types are the same - covers 'they are the same primitive type or both are Any' or the same type parameter cases
61146127 if (source === target) return Ternary.True;
6128+
61156129 if (relation === identityRelation) {
61166130 return isIdenticalTo(source, target);
61176131 }
61186132
6119- if (!(target.flags & TypeFlags.Never)) {
6120- if (target.flags & TypeFlags.Any || source.flags & TypeFlags.Never) return Ternary.True;
6121- if (source.flags & TypeFlags.Undefined) {
6122- if (!strictNullChecks || target.flags & (TypeFlags.Undefined | TypeFlags.Void)) return Ternary.True;
6123- }
6124- if (source.flags & TypeFlags.Null) {
6125- if (!strictNullChecks || target.flags & TypeFlags.Null) return Ternary.True;
6126- }
6127- if (source.flags & TypeFlags.NumberLike && target === numberType) return Ternary.True;
6128- if (source.flags & TypeFlags.Enum && target.flags & TypeFlags.Enum) {
6129- if (result = enumRelatedTo(source, target, reportErrors)) {
6130- return result;
6131- }
6132- }
6133- if (source.flags & TypeFlags.StringLike && target === stringType) return Ternary.True;
6134- if (relation === assignableRelation || relation === comparableRelation) {
6135- if (source.flags & TypeFlags.Any) return Ternary.True;
6136- if (source === numberType && target.flags & TypeFlags.Enum) return Ternary.True;
6137- }
6138- if (source.flags & TypeFlags.BooleanLike && target.flags & TypeFlags.Boolean) {
6139- return Ternary.True;
6140- }
6141- }
6133+ if (isSimpleTypeRelatedTo(source, target, relation, reportErrors ? reportError : undefined)) return Ternary.True;
61426134
61436135 if (source.flags & TypeFlags.FreshObjectLiteral) {
61446136 if (hasExcessProperties(<FreshObjectLiteralType>source, target, reportErrors)) {
@@ -6772,32 +6764,6 @@ namespace ts {
67726764 return Ternary.False;
67736765 }
67746766
6775- function enumRelatedTo(source: Type, target: Type, reportErrors?: boolean) {
6776- if (source.symbol.flags & SymbolFlags.EnumMember && source.symbol.parent === target.symbol) {
6777- return Ternary.True;
6778- }
6779- if (source.symbol.name !== target.symbol.name ||
6780- !(source.symbol.flags & SymbolFlags.RegularEnum) ||
6781- !(target.symbol.flags & SymbolFlags.RegularEnum)) {
6782- return Ternary.False;
6783- }
6784- const targetEnumType = getTypeOfSymbol(target.symbol);
6785- for (const property of getPropertiesOfType(getTypeOfSymbol(source.symbol))) {
6786- if (property.flags & SymbolFlags.EnumMember) {
6787- const targetProperty = getPropertyOfType(targetEnumType, property.name);
6788- if (!targetProperty || !(targetProperty.flags & SymbolFlags.EnumMember)) {
6789- if (reportErrors) {
6790- reportError(Diagnostics.Property_0_is_missing_in_type_1,
6791- property.name,
6792- typeToString(target, /*enclosingDeclaration*/ undefined, TypeFormatFlags.UseFullyQualifiedType));
6793- }
6794- return Ternary.False;
6795- }
6796- }
6797- }
6798- return Ternary.True;
6799- }
6800-
68016767 function constructorVisibilitiesAreCompatible(sourceSignature: Signature, targetSignature: Signature, reportErrors: boolean) {
68026768 if (!sourceSignature.declaration || !targetSignature.declaration) {
68036769 return true;
0 commit comments