-
Notifications
You must be signed in to change notification settings - Fork 12.5k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Exact types - [WIP] #28749
Exact types - [WIP] #28749
Conversation
For anyone watching: I'm waiting on some fixes for mapped type relations before picking this up again. Main thing to add is decent error messages. |
@jack-williams are you still working on this? |
No. Please feel free to take my changes and start your own experiments if you'd like. For context: The reason why I stopped persuing this is because the method of object composition in TypeScript (intersection) is essentially meaningless for exact types. I think the correct solution is row types + row polymorphism, but that is a significantly bigger challenge. |
@jack-williams that's why Flow has type object spread for exact objects instead of intersection |
@jack-williams I'm not really familiar with TS codebase, is there some docs? |
The spread type has been discussed here: #10727. The problem is that you end up with lots of similar concepts that are subtly different and it's not clear when to use what. I don't think there are any good docs for the compiler itself, or if there are, I don't know where they are located. Sorry I can't be more helpful in this regard. |
This experiment is pretty old, so I'm going to close it to reduce the number of open PRs. |
This PR doesn't have any linked issues. Please open an issue that references this PR. From there we can discuss and prioritise. |
An initial attempt at Exact Types (#12936). This is not meant be a candidate for merging, but a chance to play around and experiment. The implementation is most likely buggy (re: parser + semicolons), and the errors could be better. Please do experiment with it though!
Semantics:
I write
|T|
to denote an exact version ofT
.O
is related to an exact type|T|
if all properties inO
are inT
andO
is related toT
.|T|
is related to exact object type|U|
if all properties inT
are inU
andT
is related toU
. (Normal typing handles the converse property check ofU
inT
, I think).|T|
is related to an exact generic mapped type|U|
ifT
is a generic mapped type andT
andU
have identical constraints.Property
b
is not reported as excess because the object literal{ x: { a: string } }
appears in an exact context. The choice came about as a hack. Freshness is turned off for EPC in nested intersection and union, but freshness in needed for exactness. To avoid duplicating essentially the same object flag I chose to keep freshness but turn off EPC in certain cases. I'm not sure if this is the best thing in general, but there are some nice things about it.Examples: