Home > Net >  Why `T extends "A"` and `S extends "A"` have no overlap?
Why `T extends "A"` and `S extends "A"` have no overlap?

Time:06-10

I'm confused with a typescript compile error abut the following code:

function f<T extends "A", S extends "A">(x: T, y: S) {
  if (x === y) {
     // ERROR: This condition will always return 'false' since the types 'T' and 'S' have no overlap. ts(2367)
  }
}

playground

Obviously, T and S could have overlap, but the compiler says they have no overlap. Why does this happen and how to resolve this error?

CodePudding user response:

I guess this comment by RyanCavanaugh also applies to your case:

=== is only allowed between two operands if there is a "comparable" type relationship between them. This is similar to the check that determines if a type assertion is legal, with some extra special cases.

To see a more meaningful error from the compiler, try a cast:

function f<T extends "A", S extends "A">(x: T, y: S) {
  /**
   * Conversion of type 'T' to type 'S' may be a mistake 
   * because neither type sufficiently overlaps with the other. 
   * If this was intentional, convert the expression to 'unknown' first.
   * 
   * 'T' is assignable to the constraint of type 'S',
   * but 'S' could be instantiated with a different subtype of constraint '"A"'.
   */  
  const a = x as S;
}

To make the compiler happy, you can convert to unknown or any.

  if (x as unknown === y) {
    return true;
  }

Playground

CodePudding user response:

Still not sure, whether I get you right. But maybe this could help you

type T = `${'A' | 'B'}-${string}`;

function isName(x: T, y: T, name: string): `${T}#${T}` {
    if (x === y) { // no errors here
    }
    return 'A-first#B-second'; // valid
    return 'A-first#C-second'; // is not valid
}
  • Related