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, 12/14/2022 #51898

Closed
DanielRosenwasser opened this issue Dec 14, 2022 · 0 comments
Closed

Design Meeting Notes, 12/14/2022 #51898

DanielRosenwasser opened this issue Dec 14, 2022 · 0 comments
Labels
Design Notes Notes from our design meetings

Comments

@DanielRosenwasser
Copy link
Member

Contextually Typing Empty Arrays

#51853

  • Under strictNullChecks, the empty array is inferred as never[].

    • noImplicitAny has an "evolving array type" in some contexts, but that's an aside.
  • Works usually because never[] is assignable to everything.

  • However, if the never[] is captured in some way, you can't do anything with it. Effectively useless.

  • We want to experiment with using a contextual type if one is present for every empty array literal.

    • More nuanced than that, but that's it.
  • Arguable that a [] is really a never[] - there's nothing in it!

    • But then you can't do anything with it?
    • Write a cast/type assertion after: [] as number[].
  • One of several built-in expression forms that would benefit from more contextual type information.

    • Array literals
    • Object literals
      • readonly
      • optionality (?)
      • index signatures
  • Also, writing the cast is undesirable.

  • And if we say "write a cast", people won't want to write

    const a = {
      arr: [] as number,
    } satisfies Thing;

    so they might instead write

    const a = {
      arr: [],
    } as Thing;
  • satisfies is a red-herring right? Can observe these.

  • Feels like better behavior, but you can hit rough edges.

  • Could take the perspectives that function expressions always have their parameter types be unknown, but we don't do that - we use the contextual type.

  • Anyway, we tried out the change. Found one break.

    • Relates to us using the "reading" type of properties instead of the "writing" type.

    • Observable today anyway.

    • Playground Link

    • The "write" type is an intersection when the containing object is a union; the "read" type is a union.

    • So do we need to fix that? Possibly not.

    • Also need to fix other example.

      declare function foo<T extends { children: Error[] }>(x: T): T;
      
      // Doesn't contextually type this thing as `Error[]`.
      let zz = foo({ children: [] });
      
      // and thus, this doesn't work.
      zz.push(new Error());

const Type Parameters and Improved Contextual Type Caching

#51865

  • Every time you want precise types for literals in TS, you need to write as const.
  • Now can write const T for a given type parameter.
  • But our internals now ask over and over again for a contextual type.
    • So we now have a way to push contextual types onto a stack cache.
    • Removed polymorphic node access from tree Nodes and NodeLinks.
    • Removed try/finally as well.
      • But that try/finally was there to perform clean-up across cancellations (e.g. a CancellationToken triggered an exception).
      • Technically having moved things into NodeLinks means that we didn't need to clear state that's possibly shared across TypeCheckers - so try/finally was not necessary anymore.
        • In theory (i.e. we should verify this) we throw away the TypeChecker on every exception (including cancellations, assertion violations, whatever).
  • Do we need to have an opt-out for const contexts from type parameters?
    • Today writing nothing is the "opt-out", as const is the opt-in.
    • Making this declaration-site removes use-site control.
  • There are some ways to perform an "opt-out".
    • You can write an explicit type argument.
    • You can also write satisfies unknown to defeat the contextual type from any const type parameters.
      • Not perfect - you might have function f<const T extends SomeSpecificType>(...)
  • Otherwise seems okay.
@DanielRosenwasser DanielRosenwasser added the Design Notes Notes from our design meetings label Dec 14, 2022
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

2 participants