[Feature request]type level equal operator
See original GitHub issueoriginal issue: #27024
Search Terms
- Type System
- Equal
Suggestion
T1 == T2
Use 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 Error
Checklist
My suggestion meets these guidelines:
- This wouldn’t be a breaking change in existing TypeScript / JavaScript code
- This wouldn’t change the runtime behavior of existing JavaScript code
- This could be implemented without emitting different JS based on the types of the expressions
- This isn’t a runtime feature (e.g. new expression-level syntax)
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) - https://github.com/microsoft/TypeScript/issues/27024#issuecomment-568233987
- doesn’t work properly with
{}
types - https://github.com/microsoft/TypeScript/issues/27024#issuecomment-778623742 - doesn’t work properly with
Equal<{ x: 1 } & { y: 2 }, { x: 1, y: 2 }>
- https://github.com/microsoft/TypeScript/issues/27024#issuecomment-907601804
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
Issue Analytics
- State:
- Created 2 years ago
- Reactions:5
- Comments:14 (7 by maintainers)
Top GitHub Comments
👀
These types are very much different;
T extends { p: string } ? true : false
istrue | false
for one andfalse
for the otherAs much as I would like to have a reliable equality check, I have to agree with Ryan about people disagreeing on what should be equal.
For instance, I don’t think intersection of functions should be equal, because this operation is not commutative:
If you want an equal operator in order to catch bugs in your types, you will probably want
Equal<A, B>
to be false. If you want it for some other reason, maybe your definition of “equality” in that specific context will be different.Concerning performance, if this kind of check only appears in a test suite, of course you want the said test suite to run fast, but it is not as critical as making the type checking of your production code fast, so I would not mind a slow workaround if it were reliable.
I have learned to use conditional types in times when using an intersection would have made logical sense, because intersections have lots of quirks. What would “equality” mean in an unsound type system?