sindresorhus / type-fest

A collection of essential TypeScript types
Creative Commons Zero v1.0 Universal
14.47k stars 549 forks source link

`IsEqual` identity issues #537

Open trevorade opened 1 year ago

trevorade commented 1 year ago

There are two self-identity bugs that can pretty simply be fixed: TS Playground

Both of these evaluate to false:

IsEqual<{a: 1} & {a: 1}, {a: 1}>
IsEqual<{a: 1} | {a: 1}, {a: 1}>

The fix is to expand the check a touch:

type IsEqual<A, B> =
    (<G>() => G extends A & G | G ? 1 : 2) extends
    (<G>() => G extends B & G | G ? 1 : 2)
    ? true
    : false;

There's also this intersection bug but I'm unaware of a fix: TS Playground

This evaluates to false:

IsEqual<{a: 1} & {b: 2}, {a: 1, b: 2}>

Upvote & Fund

Fund with Polar

tommy-mitchell commented 1 year ago

https://github.com/Microsoft/TypeScript/issues/27024#issuecomment-845655557 has a robust solution that seems to solve this (TS Playground link). It's a much longer type though, and seemingly not perfect either.

tommy-mitchell commented 1 year ago

Seemingly, according to Update 1 on this StackOverflow answer, under TypeScript's implementation {a: 1} & {b: 2} and {a: 1, b: 2} aren't actually the same. Not sure if that means they should or shouldn't be equal on the type level, though.

microsoft/TypeScript#48100 is an open issue tracking type equality and its definition. Seems that a recursive Simplify can fix some issues with equality as well.