diff --git a/src/compiler/checker.ts b/src/compiler/checker.ts
index a3abe1dc5b5..fb96ca0813a 100644
--- a/src/compiler/checker.ts
+++ b/src/compiler/checker.ts
@@ -13321,7 +13321,14 @@ namespace ts {
}
}
else if (isReadonlyArrayType(target) ? isArrayType(source) || isTupleType(source) : isArrayType(target) && isTupleType(source) && !source.target.readonly) {
- return isRelatedTo(getIndexTypeOfType(source, IndexKind.Number) || anyType, getIndexTypeOfType(target, IndexKind.Number) || anyType, reportErrors);
+ if (relation !== identityRelation) {
+ return isRelatedTo(getIndexTypeOfType(source, IndexKind.Number) || anyType, getIndexTypeOfType(target, IndexKind.Number) || anyType, reportErrors);
+ }
+ else {
+ // By flags alone, we know that the `target` is a readonly array while the source is a normal array or tuple
+ // or `target` is an array and source is a tuple - in both cases the types cannot be identical, by construction
+ return Ternary.False;
+ }
}
// Consider a fresh empty object literal type "closed" under the subtype relationship - this way `{} <- {[idx: string]: any} <- fresh({})`
// and not `{} <- fresh({}) <- {[idx: string]: any}`
diff --git a/tests/cases/fourslash/quickinfoExpressionTypeNotChangedViaDeletion.ts b/tests/cases/fourslash/quickinfoExpressionTypeNotChangedViaDeletion.ts
new file mode 100644
index 00000000000..01656aea566
--- /dev/null
+++ b/tests/cases/fourslash/quickinfoExpressionTypeNotChangedViaDeletion.ts
@@ -0,0 +1,15 @@
+///
+////type TypeEq = (() => T extends A ? 1 : 2) extends (() => T extends B ? 1 : 2) ? true : false;
+////
+////const /*2*/test1: TypeEq = false;
+////
+////declare const foo: [number, ...number[]];
+////declare const bar: number[];
+////
+////const /*1*/test2: TypeEq = false;
+
+goTo.marker("1");
+verify.quickInfoIs("const test2: false");
+
+goTo.marker("2");
+verify.quickInfoIs("const test1: false");