Closed
Description
Allowing Calls Ending with Unions
- Today, you can already spread in a value that's a tuple when performing a call.
- Naturally, the next step is to make this work for tuples as well.
- In the example in Error when spreading a union of tuples in a call #42508, the right fix is to switch the signature to take
a: number, b: number, c?: number
instead of two signatures.- May not be in control of the signature.
- This approach just tries to create a new "combined" tuple for the effective argument list.
- So
[number, number] | [string, number]
becomes[number, string | number]
.
- So
- Technically this is conservative. Won't work for
[number, number] | [string, string]
. - Internals get gnarly. Have to funnel around more information about the minimum argument count that might be passed in.
- Ideally we could try out multiple signatures. However, architecturally TypeScript assumes it can assign types for symbols once and never again, and this is a large boulder to move. It's been a long-standing problem in the compiler. But also, doing so could cause us to do a lot of work.
- Stack of PRs before that's reasonable for us to do.
- [[Meta: What's the canonical issue for this?]]
Covariance breaks when checking for undefined
in a type
- We use the identity relation when comparing
T
s inFoo extends T ? A : B
to figure out variance here.- In
type Setter<T> = undefined extends T ? () => undefined : {};
, we decide thatT
is invariant. - Transitively,
U
is invariant intype Test<U> = { 0: Setter<U> };
which is undesirable. Direct structural instantiation will often permit types.
- In
- We have a PR that fixes this by marking
T
as unmeasurable (Mark conditional extends as Unmeasurable and use a conditional-opaque wildcard for type erasure #43887)- Breaks things...
- Makes things slower too because we can't trust variance measurements...
- Falling back to structural checking is very very slow.
- We also have anecdotally seen types that rely on the fact that TypeScript uses the identity relationship to compare conditional types in this way.
- Had a PR from @Andarist which introduced new variance measurement types which saved some work - basically signaled "unmeasurable" but require the identity relationship.
- Basically in the example, variance of
T
inSetter
is marked as a special type of unmeasurable. Instances ofSetter
would be compared in an invariant manner; however, any variance checks for type parameters that are fed intoSetter
(i.e.U
) are marked as unmeasurable. - Still might end up in structural checks anyway.
- Basically in the example, variance of
- Feels like at that point, might as well just mark as unmeasurable.
- Just had to do a revert of correctly marking types as
Unreliable
, but not ofUnmeasurable
. - We need Better Variance™️?
- It's not great, but maybe it's okay to be more conservative?
- Not just a matter of being more conservative. In our type system, conditional types can make choice; but they may make choices based on incorrect variance checks.
- Can defeat this with an
Evaluate
alias. - If we had a better way to do structural checking more efficiently, that would allow us to fix these issues up.
- Conclusion:
- We don't know!
- We want a running list of places where variance is measured incorrectly.