Skip to content
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

Design Meeting Notes, 7/28/2023 #55188

Closed
DanielRosenwasser opened this issue Jul 28, 2023 · 6 comments
Closed

Design Meeting Notes, 7/28/2023 #55188

DanielRosenwasser opened this issue Jul 28, 2023 · 6 comments
Labels
Design Notes Notes from our design meetings

Comments

@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented Jul 28, 2023

Allowing Calls Ending with Unions

#55185

  • 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].
  • 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

#55161

  • We use the identity relation when comparing Ts in Foo extends T ? A : B to figure out variance here.
    • In type Setter<T> = undefined extends T ? () => undefined : {};, we decide that T is invariant.
    • Transitively, U is invariant in type Test<U> = { 0: Setter<U> }; which is undesirable. Direct structural instantiation will often permit types.
  • 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 in Setter is marked as a special type of unmeasurable. Instances of Setter would be compared in an invariant manner; however, any variance checks for type parameters that are fed into Setter (i.e. U) are marked as unmeasurable.
    • Still might end up in structural checks anyway.
  • 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 of Unmeasurable.
  • 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.
@DanielRosenwasser DanielRosenwasser added the Design Notes Notes from our design meetings label Jul 28, 2023
@Andarist
Copy link
Contributor

Had a PR from @Andarist which introduced new variance measurement types which saved some work - basically signaled "unmeasurable" but require the identity relationship.

Hm, I don't recall putting up such a PR 😅

@DanielRosenwasser
Copy link
Member Author

DanielRosenwasser commented Jul 28, 2023

@weswigham maybe you put it up? 😄

@RyanCavanaugh
Copy link
Member

Sounds like I get to break out the Cursed? label again?

@fatcerberus
Copy link

undefinded

Heh, you kept the typo.

@fatcerberus
Copy link

We also have anecdotally seen types that rely on the fact that TypeScript uses the identity relationship to compare conditional types in this way.

In particular, this Equals type is quite common in the wild because it is (to my knowledge) the only way to leverage the isTypeIdenticalTo check in TS code, which can even be used to distinguish e.g. anys from other types.

@DanielRosenwasser
Copy link
Member Author

@fatcerberus I fixed it :D

@RyanCavanaugh Cursed came up in the meeting!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Design Notes Notes from our design meetings
Projects
None yet
Development

No branches or pull requests

4 participants