Add the comparability relationship to the spec (attempt two)#20686
Add the comparability relationship to the spec (attempt two)#20686DanielRosenwasser wants to merge 2 commits intospec-updatefrom
Conversation
|
I don't know if I covered this feedback:
|
| * *T* is an enum member type, *S* is a literal type, and the literal values of *S* and *T* are identical. | ||
| * *S* is a literal type and *T* is the base primitive type of *S*. | ||
| * *T* is a literal type and *S* is the base primitive type of *T*. | ||
| * *S* is a union type and some constituent type of *S* is comparable to *T*. |
There was a problem hiding this comment.
Is this relation 100% symmetric? Can we just say that up front and cut this in half?
There was a problem hiding this comment.
Or even if it's not, parcel out the symmetric relations, e.g. S is assignable to T if any of the following are true for S* = S, T* = T or for S* = T, T* = S... (all symmetric properties here in terms of S* / T*)
There was a problem hiding this comment.
@RyanCavanaugh I don't quite understand what you mean. But I'd prefer not to combine these operations so that a reader (or a spec writer 😉) can manually do a diff between the assignability and comparability sections on their own
| * the non-primitive object type is comparable to and from any other object type, and | ||
| * when relating any two signatures, each signature is always instantiated using type Any for all type arguments. | ||
|
|
||
| While the comparable relation is often applied bidirectionally on a pair of types, it is not a symmetric relationship. |
There was a problem hiding this comment.
Answers my above question but deserves a counterexample
| * *S* is an enum type and *T* is the primitive type Number. | ||
| * *S* is the Never type. | ||
| * *S* is the Undefined type and *T* is the Void type. | ||
| * *S* is either the Undefined or Null type, and strict null checks ([#strict-null-checks]) are disabled. |
There was a problem hiding this comment.
I thought we weren't talking about non-strict in the spec.
There was a problem hiding this comment.
You already used this in your other PR :(
| * *S* is a numeric enum or numeric enum member type and *T* is the primitive type Number. | ||
| * *S* and *T* are both enum member types with respective containing enum types *E* and *F* and | ||
| * *E* is a subtype of *F*. | ||
| * *S* and *T* are both non-const enum types with the same declared name, and |
| * *S* is a union type and each constituent type of *S* is a subtype of *T*. | ||
| * *S* is an intersection type and at least one constituent type of *S* is a subtype of *T*. | ||
| * *T* is a union type and *S* is a subtype of at least one constituent type of *T*. | ||
| * *T* is an intersection type and *S* is a subtype of each constituent type of *T*. |
There was a problem hiding this comment.
Already taken care of above in the intro to the section.
|
|
||
| *TODO: Document the base primitive type.* | ||
|
|
||
| Types are required to be *comparable* in certain circumstances, such as part of when checking whether two values of given types might be equal at runtime using operators like '===', or when using a type assertion. |
There was a problem hiding this comment.
Shouldn't this list be complete and authoritative? I don't think it's going to be defined elsewhere. And based on your findings, it looks like it already is complete, it just needs to say that these are the only places that comparability happens.
| * *S* is either the Undefined or Null type, and strict null checks ([#strict-null-checks]) are disabled. | ||
| * *S* is an object type and *T* is the non-primitive `object` type. | ||
| * *T* is an object type and *S* is the non-primitive `object` type. | ||
| * *S* or *T* is a numeric enum or numeric enum member type and the other is the primitive type Number. |
There was a problem hiding this comment.
This applies to strings too, doesn't it?
| * *S* is an intersection type and at least one constituent type of *S* is comparable to *T*. | ||
| * *T* is a union type and *S* is comparable to at least one constituent type of *T*. | ||
| * *T* is an intersection type and *S* is comparable to each constituent type of *T*. | ||
| * *T* is a type parameter and *S* is a mapped type *{ [P in keyof X]: Y }*, and *Y* is comparable to *X[P]*. |
There was a problem hiding this comment.
I think that you have to say that X is comparable (or identical?) to T if you don't just use keyof T in the mapped type itself.
| * *S* is a key query type *keyof S'* and *T'* is comparable to *S'*. | ||
| * *S* is comparable to *keyof C* where *C* is the constraint of *S*. | ||
| * *T* is an indexed access type *T'[K]* and *S* is comparable to *C[K]* where *C* is the constraint of *T'*. | ||
| * *T* is a mapped type *{ [P in K]: X }*, *S* is not a mapped type, *keyof S* is identical to *K*, and *S[K]* is comparable to *X*. |
There was a problem hiding this comment.
the last clause should be S[P] is comparable to X, not S[K].
7ebb064 to
1c5bdd3
Compare
1c5bdd3 to
2fb84d5
Compare
|
@DanielRosenwasser can we get these in? |
|
@DanielRosenwasser I would like to have this and its friends be merged or closed |
Fixes #17214.
Subsumes #17215.