Description
Object Spreads and Union Types
-
One set of users: have been working with long builds, throw 8GB at it
- Recent change: more gigs, compilation "seems to never terminate".
-
They have a huge object type written like
const cssProps = { ...{yadda && { backgroundColor: "...", color: "...", // ... }} // ... 100 more of these }
-
This ends up creating a MASSIVE union type based on making a conditional property.
-
The users don't want a union, they just want a big old blob of optional properties.
-
We could just "recognize the pattern" and provide a "weaker" type (i.e. one type with lots of optionals instead of a union where every other union member makes the property
undefined
). -
In 3.8, we added this logic, but only for single-property objects. We were afraid to do this too broadly.
-
Other workarounds?
as CSSProperties
- Some helper function.
-
Can we leverage a contextual type?
- Well the heuristic can't just look and say "do I have a union?"
-
Some feel like we should just always do this.
- Could also say that, when performing a spread, "do I have a conditional type where the property type is optional? If so, create an optional property."
-
One option might be to provide a quick fix to write the all-optional property object type when the expression is too complex.
-
Sounds like we always want to use the all-optional properties, but can't do that for 4.1.
- Sounds like we also need a limiter for 4.1 though.
throw
Types
- If a
throw
type "ever comes to pass", it becomes an error. - In principle, really like the idea to convey reasons of why conditional types didn't actually work.
- "Signaling
never
s, ornever
s with a reason."
- "Signaling
- Issue: "if it ever gets evaluated" leaks implementation details of instantiation.
- Our type system's instantiation semantics aren't strictly evaluated, but it's not always lazily evaluated either!
- Basically non-strict is the best you can say.
- Lots of places where instantiation can also be surprising (e.g. looking at constraints).
- Our type system's instantiation semantics aren't strictly evaluated, but it's not always lazily evaluated either!
- Surprising how well errors can be tied back to specific locations.
- That's
currentNode
, we've had that for a while, works decently well. - Though could end up with instantiation anywhere, so...
- That's
- Potential performance problem?
- When you use these instead of
never
in the tail, you end up with more types. - Could potentially intern these though, not necessarily the biggest concern.
- When you use these instead of
- Would be ideal if this built on
never
, especially because of unioning semantics.- Sometimes you don't want that either.
- It sounds like there are really two things:
- a signaling
never
type - a signaling "poison" type
- the anti-
any
- the anti-
- a signaling
- Conclusion: like the idea, not necessarily this as the future direction. Two potential directions of "signaling
never
" and signaling "anti-any
".
Conditional Assignability
-
[[Look how our type helpers look like parser combinators now.]]
-
But you can only trigger the inference on these type aliases for literals by writing them in call positions.
-
What if you could?
// Concept type Digit = match S extends string => S extends '0' | '1' | '2' | '3' | '4' | '5' | '6' | '7' | '8' | '9' ? true : false;
-
Mental model:
- When relating a type
Foo
to aDigit
,S
is bound toFoo
, and is then related to that. - The relationship succeeds when the source matches the constraint (
string
) and the type then evaluates totrue
. - When used as a source type, the type is the constraint.
- When relating a type
-
Out of time.