Let's assume that we have following definition of Equal
type:
type Equal<X, Y> = (X extends Y ? (Y extends X ? true : false) : false);
Using that definition, we can create other types:
type Type1 = Equal<boolean, boolean> // => boolean
type Type2 = Equal<boolean, string> // => false
type Type3 = Equal<string, string> // => true
Looking at the types inferred by TypeScript, it shows information as in comments above. While Type2
and Type3
work as expected, type for Type1
is inferred as boolean
. I would expect it to be true
.
What is the reason for it?
I used TypeScript v5.6.3 in online sandbox (typescriptlang).
I believe this is happening because TypeScript is splitting booleans into a union internally. So boolean
gets converted to true | false
.
A neat trick is to wrap the values in a tuple like this (so types get treated as a single unit):
type Equal<X, Y> = [X] extends [Y] ? ([Y] extends [X] ? true : false) : false;
Now the results are correct.
Also if you want to check for exact equality you can use this utility type, which uses overloading and conditional types:
type Equals<X, Y> = (<T>() => T extends X ? 1 : 2) extends <
T
>() => T extends Y ? 1 : 2
? true
: false;