mirror of
https://github.com/microsoft/TypeScript.git
synced 2025-11-18 17:21:48 +00:00
Simplify indexTypesRelatedTo function
This commit is contained in:
+39
-73
@@ -5760,9 +5760,9 @@ namespace ts {
|
||||
if (result) {
|
||||
result &= signaturesRelatedTo(source, target, SignatureKind.Construct, reportErrors);
|
||||
if (result) {
|
||||
result &= stringIndexTypesRelatedTo(source, originalSource, target, reportErrors);
|
||||
result &= indexTypesRelatedTo(source, originalSource, target, IndexKind.String, reportErrors);
|
||||
if (result) {
|
||||
result &= numberIndexTypesRelatedTo(source, originalSource, target, reportErrors);
|
||||
result &= indexTypesRelatedTo(source, originalSource, target, IndexKind.Number, reportErrors);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -5964,10 +5964,10 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
function eachPropertyRelatedTo(source: Type, target: Type, numericPropertiesOnly: boolean, reportErrors: boolean): Ternary {
|
||||
function eachPropertyRelatedTo(source: Type, target: Type, kind: IndexKind, reportErrors: boolean): Ternary {
|
||||
let result = Ternary.True;
|
||||
for (const prop of getPropertiesOfObjectType(source)) {
|
||||
if (!numericPropertiesOnly || isNumericLiteralName(prop.name)) {
|
||||
if (kind === IndexKind.String || isNumericLiteralName(prop.name)) {
|
||||
const related = isRelatedTo(getTypeOfSymbol(prop), target, reportErrors);
|
||||
if (!related) {
|
||||
if (reportErrors) {
|
||||
@@ -5981,82 +5981,48 @@ namespace ts {
|
||||
return result;
|
||||
}
|
||||
|
||||
function stringIndexTypesRelatedTo(source: Type, originalSource: Type, target: Type, reportErrors: boolean): Ternary {
|
||||
if (relation === identityRelation) {
|
||||
return indexTypesIdenticalTo(IndexKind.String, source, target);
|
||||
function indexInfoRelatedTo(sourceInfo: IndexInfo, targetInfo: IndexInfo, reportErrors: boolean) {
|
||||
const related = isRelatedTo(sourceInfo.type, targetInfo.type, reportErrors);
|
||||
if (!related && reportErrors) {
|
||||
reportError(Diagnostics.Index_signatures_are_incompatible);
|
||||
}
|
||||
const targetInfo = getIndexInfoOfType(target, IndexKind.String);
|
||||
if (targetInfo) {
|
||||
if ((targetInfo.type.flags & TypeFlags.Any) && !(originalSource.flags & TypeFlags.Primitive)) {
|
||||
// non-primitive assignment to any is always allowed, eg
|
||||
// `var x: { [index: string]: any } = { property: 12 };`
|
||||
return Ternary.True;
|
||||
return related;
|
||||
}
|
||||
|
||||
function indexTypesRelatedTo(source: Type, originalSource: Type, target: Type, kind: IndexKind, reportErrors: boolean) {
|
||||
if (relation === identityRelation) {
|
||||
return indexTypesIdenticalTo(source, target, kind);
|
||||
}
|
||||
const targetInfo = getIndexInfoOfType(target, kind);
|
||||
if (!targetInfo || ((targetInfo.type.flags & TypeFlags.Any) && !(originalSource.flags & TypeFlags.Primitive))) {
|
||||
// Index signature of type any permits assignment from everything but primitives
|
||||
return Ternary.True;
|
||||
}
|
||||
const sourceInfo = getIndexInfoOfType(source, kind) ||
|
||||
kind === IndexKind.Number && getIndexInfoOfType(source, IndexKind.String);
|
||||
if (sourceInfo) {
|
||||
return indexInfoRelatedTo(sourceInfo, targetInfo, reportErrors);
|
||||
}
|
||||
if (isObjectLiteralType(source)) {
|
||||
let related = Ternary.True;
|
||||
if (kind === IndexKind.String) {
|
||||
const sourceNumberInfo = getIndexInfoOfType(source, IndexKind.Number);
|
||||
if (sourceNumberInfo) {
|
||||
related = indexInfoRelatedTo(sourceNumberInfo, targetInfo, reportErrors);
|
||||
}
|
||||
}
|
||||
const sourceInfo = getIndexInfoOfType(source, IndexKind.String);
|
||||
if (!sourceInfo) {
|
||||
if (isObjectLiteralType(source)) {
|
||||
return eachPropertyRelatedTo(source, targetInfo.type, /* numericPropertiesOnly*/ false, reportErrors);
|
||||
}
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Index_signature_is_missing_in_type_0, typeToString(source));
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
const related = isRelatedTo(sourceInfo.type, targetInfo.type, reportErrors);
|
||||
if (!related) {
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Index_signatures_are_incompatible);
|
||||
}
|
||||
return Ternary.False;
|
||||
if (related) {
|
||||
related &= eachPropertyRelatedTo(source, targetInfo.type, kind, reportErrors);
|
||||
}
|
||||
return related;
|
||||
}
|
||||
return Ternary.True;
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Index_signature_is_missing_in_type_0, typeToString(source));
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
|
||||
function numberIndexTypesRelatedTo(source: Type, originalSource: Type, target: Type, reportErrors: boolean): Ternary {
|
||||
if (relation === identityRelation) {
|
||||
return indexTypesIdenticalTo(IndexKind.Number, source, target);
|
||||
}
|
||||
const targetInfo = getIndexInfoOfType(target, IndexKind.Number);
|
||||
if (targetInfo) {
|
||||
if ((targetInfo.type.flags & TypeFlags.Any) && !(originalSource.flags & TypeFlags.Primitive)) {
|
||||
// non-primitive assignment to any is always allowed, eg
|
||||
// `var x: { [index: number]: any } = { property: 12 };`
|
||||
return Ternary.True;
|
||||
}
|
||||
const sourceStringInfo = getIndexInfoOfType(source, IndexKind.String);
|
||||
const sourceNumberInfo = getIndexInfoOfType(source, IndexKind.Number);
|
||||
if (!(sourceStringInfo || sourceNumberInfo)) {
|
||||
if (isObjectLiteralType(source)) {
|
||||
return eachPropertyRelatedTo(source, targetInfo.type, /* numericPropertiesOnly*/ true, reportErrors);
|
||||
}
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Index_signature_is_missing_in_type_0, typeToString(source));
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
let related: Ternary;
|
||||
if (sourceStringInfo && sourceNumberInfo) {
|
||||
// If we know for sure we're testing both string and numeric index types then only report errors from the second one
|
||||
related = isRelatedTo(sourceStringInfo.type, targetInfo.type, /*reportErrors*/ false) ||
|
||||
isRelatedTo(sourceNumberInfo.type, targetInfo.type, reportErrors);
|
||||
}
|
||||
else {
|
||||
related = isRelatedTo((sourceStringInfo || sourceNumberInfo).type, targetInfo.type, reportErrors);
|
||||
}
|
||||
if (!related) {
|
||||
if (reportErrors) {
|
||||
reportError(Diagnostics.Index_signatures_are_incompatible);
|
||||
}
|
||||
return Ternary.False;
|
||||
}
|
||||
return related;
|
||||
}
|
||||
return Ternary.True;
|
||||
}
|
||||
|
||||
function indexTypesIdenticalTo(indexKind: IndexKind, source: Type, target: Type): Ternary {
|
||||
function indexTypesIdenticalTo(source: Type, target: Type, indexKind: IndexKind): Ternary {
|
||||
const targetInfo = getIndexInfoOfType(target, indexKind);
|
||||
const sourceInfo = getIndexInfoOfType(source, indexKind);
|
||||
if (!sourceInfo && !targetInfo) {
|
||||
|
||||
Reference in New Issue
Block a user