Last updated: Feb 28, 2024
Reading time·5 min
The error "This comparison appears to be unintentional because the types 'X' and 'Y' have no overlap" occurs when a condition is guaranteed to have the same outcome 100% of the time.
To solve the error, correct the logic in the condition or use a type assertion if TypeScript is getting confused.
Here are 3 examples of how the error occurs.
const num = 30; const str = '30'; // ⛔️ Error: This comparison appears to be unintentional because the types 'number' and 'string' have no overlap. if (num === str) { console.log('success'); } // --------------------------------------------------------- const str2 = 'bobby'; // ⛔️ This comparison appears to be unintentional because the types '"bobby"' and '"hadz"' have no overlap. if (str2 === 'bobby' && str2 === 'hadz') { console.log('success'); } // --------------------------------------------------------- export enum Sizes { Small = 'S', Medium = 'M', Large = 'L', } let size: Sizes = Sizes.Medium; [1, 2].forEach((_) => { size = Sizes.Large; }); console.log(size); // 👉️ "L" // ⛔️ This comparison appears to be unintentional because the types 'Sizes.Medium' and 'Sizes.Large' have no overlap. if (size === Sizes.Large) { console.log('success'); }
In the first example, we are trying to compare two values of a different type
which is guaranteed to return false
.
const num = 30; const str = '30'; // ⛔️ Error: This comparison appears to be unintentional because the types 'number' and 'string' have no overlap. if (num === str) { console.log('success'); }
To solve the error in this scenario:
console.log
the values in the condition.const num = 30; const str = '30'; if (num === Number(str)) { console.log('success'); }
We used the Number()
constructor to convert the string to a number before
comparing the values.
Now the values on the left and right-hand sides are compatible types, so the comparison works as expected.
In the second example, we got the error because we used the logical AND (&&) operator instead of the logical OR (||) operator.
const str = 'bobby'; // ⛔️ This comparison appears to be unintentional because the types '"bobby"' and '"hadz"' have no overlap. if (str === 'bobby' && str === 'hadz') { console.log('success'); }
The str
variable cannot possibly have a value of bobby
and hadz
at the
same time, so the condition is always going to return false
.
To solve the error, use the logical OR (||) operator instead.
const str = 'bobby'; if (str === 'bobby' || str === 'hadz') { console.log('success'); // 👉️ this runs }
When the logical OR (||) operator is used in an if
statement, at least one of
the conditions has to be met for the if
block to run.
When the logical AND (&&) operator is used in an if
statement, both conditions
have to be met for the if
block to run.
Logical OR (||) returns the value to the right if the value to the left is falsy, otherwise, the value to the left is returned.
Logical AND (&&) returns the value to the left if it's falsy, otherwise, the value to the right is returned.
The error also occurs if we use the logical NOT (!) operator incorrectly when comparing values.
const str1 = 'bobby'; const str2 = Math.random() > 0.5 ? 'bobby' : 'hadz'; // ⛔️ This comparison appears to be unintentional because // the types 'boolean' and 'string' have no overlap. if (str1 === 'bobby' && !str1 !== str2) { console.log('success'); }
Notice that we used the logical NOT (!) operator in the expression:
!str1 !== str2
We didn't wrap the expression in parentheses, so the logical NOT (!) operator simply negates the value to the left and converts it to a boolean.
To solve the error, wrap the expression in parentheses.
const str1 = 'bobby'; const str2 = Math.random() > 0.5 ? 'bobby' : 'hadz'; // ✅ wrapped the expression in parentheses if (str1 === 'bobby' && !(str1 !== str2)) { console.log('success'); }
Now we negate the expression str1 !== str2
rather than just the value stored
in the str1
variable, so everything works as expected.
In some cases, the issue is not in our code but with limitations in the TypeScript compiler.
export enum Sizes { Small = 'S', Medium = 'M', Large = 'L', } let size: Sizes = Sizes.Medium; [1, 2].forEach((_) => { size = Sizes.Large; }); console.log(size); // 👉️ "L" // ⛔️ This comparison appears to be unintentional because the types 'Sizes.Medium' and 'Sizes.Large' have no overlap. if (size === Sizes.Large) { console.log('success');// 👉️ this runs }
The code sample shows that the size
variable gets set to Sizes.Large
in the
forEach()
method but TypeScript doesn't know about it.
You can read more about comparing enums in this article.
In this case, the easiest way to solve the error is to use a type assertion.
export enum Sizes { Small = 'S', Medium = 'M', Large = 'L', } let size: Sizes = Sizes.Medium; [1, 2].forEach((_) => { size = Sizes.Large; }); console.log(size); // 👉️ "L" // ✅ Use type assertion if ((size as Sizes) === Sizes.Large) { console.log('success'); // 👉️ this runs }
We used a
type assertion
to type the size
variable as Sizes
.
By using a type assertion, we effectively tell TypeScript that the size
variable is guaranteed to have a type of Sizes
, so don't worry about it.
We could have also used a type assertion when declaring the size
variable.
export enum Sizes { Small = 'S', Medium = 'M', Large = 'L', } // 👇️ Use type assertion here 👇️ let size: Sizes = Sizes.Medium as Sizes; [1, 2].forEach((_) => { size = Sizes.Large; }); console.log(size); // 👉️ "L" if (size === Sizes.Large) { console.log('success'); // 👉️ this runs }
This is a bit better in this case because we wouldn't have to repeat ourselves
every time we use the size
variable in a comparison.
In this case, we solved the error by convincing TypeScript that the condition is not guaranteed to have the same outcome 100% of the time.
Here is another example of how the error occurs.
// ⛔️ src/index.ts:19:5 - error TS2367: // This comparison appears to be unintentional because the types // 'ProcessEnv' and 'string' have no overlap. if (process.env === 'development') { console.log('dev'); }
We are trying to compare the process.env
object to the string development
which causes the issue.
To solve the error, we have to make sure that the values on the left-hand and right-hand sides are of compatible types.
In this case, we have to access a property on the process.env
object and
compare the property to the string.
if (process.env.NODE_ENV === 'production') { console.log('prod'); } else if (process.env.NODE_ENV === 'development') { console.log('dev'); } else { console.log(process.env.NODE_ENV); }
The NODE_ENV
property is just an example.
However, if the property returns a value of type string
, the comparison is
valid.
Make sure:
console.log
the values in the condition.You can learn more about the related topics by checking out the following tutorials: