-
Notifications
You must be signed in to change notification settings - Fork 13k
Description
original issue: #27024
Search Terms
- Type System
- Equal
Suggestion
T1 == T2Use Cases
TypeScript type system is highly functional. Type level testing is required. However, we can not easily check type equivalence. I want a type-level equivalence operator there.
It is difficult for users to implement any when they enter. I implemented it, but I felt it was difficult to judge the equivalence of types including any.
Examples
type A = number == string;// false type B = 1 == 1;// true type C = any == 1;// false type D = 1 | 2 == 1;// false type E = Head<[1,2,3]> == 1;// true(see:#24897) type F = any == never;// false type G = [any] == [number];// false type H = {x:1}&{y:2} == {x:1,y:2}// true function assertType<_T extends true>(){} assertType<Head<[1,2,3]> == 1>(); assertType<Head<[1,2,3]> == 2>();// Type ErrorChecklist
My suggestion meets these guidelines:
This wouldn't be a breaking change in existing TypeScript / JavaScript codeThis wouldn't change the runtime behavior of existing JavaScript codeThis could be implemented without emitting different JS based on the types of the expressionsThis isn't a runtime feature (e.g. new expression-level syntax)To pick up a draggable item, press the space bar. While dragging, use the arrow keys to move the item. Press space again to drop the item in its new position, or press escape to cancel.
workarounds
to summarize the discussion in #27024, the accepted solution was:
export type Equals<X, Y> =
(<T>() => T extends X ? 1 : 2) extends
(<T>() => T extends Y ? 1 : 2) ? true : false;
however there are many edge cases where it fails:
- doesn't work properly with overloads (function type intersections) - [Feature request]type level equal operator #27024 (comment)
- doesn't work properly with
{}
types - [Feature request]type level equal operator #27024 (comment) - doesn't work properly with
Equal<{ x: 1 } & { y: 2 }, { x: 1, y: 2 }>
- [Feature request]type level equal operator #27024 (comment)
there were some other workarounds posted that attempted to address these problems, but they also had cases where they didn't work properly.
what "equal" means
i think it's important for it to treat structurally equal types as equal. for example { a: string, b: number; }
should be considered equal to { a: string } & { b: number; }
as they behave exactly the same
Activity
RyanCavanaugh commentedon Mar 3, 2022
What I see in that thread is that people have differing definitions of "equal" that are possibly in conflict, e.g. #27024 (comment). If you want to reopen this please fill out something more substantial in the template that goes into the shortcomings, current trade-offs, and desired semantics.
DetachHead commentedon Mar 4, 2022
@RyanCavanaugh i don't think there was any disagreement on the definition of "equal" but rather people finding edge cases that the workarounds didn't account for. as far as i can tell everyone in that discussion seems to agree on what types should be considered equal.
regardless, i've updated the issue with more information. can it be re-opened (or can the original issue be re-opened)?
RyanCavanaugh commentedon Mar 4, 2022
👀
These types are very much different;
T extends { p: string } ? true : false
istrue | false
for one andfalse
for the otherDetachHead commentedon Mar 5, 2022
oops, updated with a better example
EqualsWrapped
isn't recursive DetachHead/ts-helpers#128HeavenSky commentedon Jul 19, 2022
HeavenSky commentedon Jul 19, 2022
So, this solution is not quite right.
ecyrbe commentedon Jul 23, 2022
if you want to handle this case. you can use this :
Playground Link
22 remaining items