typescriptbooleantype-inference

Why Typescript infers specific type, while logically it should be different type


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).


Solution

  • 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;