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, 1/10/2020 #36138

Closed
DanielRosenwasser opened this issue Jan 11, 2020 · 1 comment
Closed

Design Meeting Notes, 1/10/2020 #36138

DanielRosenwasser opened this issue Jan 11, 2020 · 1 comment
Labels
Design Notes Notes from our design meetings

Comments

@DanielRosenwasser
Copy link
Member

import type Changes

#36092

  • Can't use typeof type queries on import type.
    • import type only imported the type side of things! (as well as the namespace space)
  • Now, import type imports the value meaning - it imports everything - but we'll report an error on anything whose usage would
  • Seems like import type is a misnomer.
    • Doesn't just import types!
  • We also do typeof import(...).SomeStuff which is a special type of way to reference types.
  • What does Flow do?
    • Does what import type originally does (only imports types), but the issue was marked as resolved and closed.
    • Flow has import typeof separately.
  • What about the fact that import type will now shadow values?
  • import type { Promise } from "bluebird";
  • Should have a test case for weird type-directed emit corner case.
    • Needs to issue an error, and mark an import as used for values.
  • Seems like the PR adds some overhead.
    • 3%!?

    • Why? Well, whenever you reference an alias, we need to determine whether a module is transitively marked as import/export type to know whether an import is used in value position.

      // ./foo.ts
      let Foo = 100;
      export type { Foo };
      
      // ./bar.ts
      import { Foo } from "./foo.js";
      
      // Need to error here, but this requires deeper resolution.
      Foo;
    • Had a suggestion that anything that's exporting using export type can only be imported using import type.

    • Unclear if this is really the bottleneck - maybe several walks.

  • Implementation stuff
    • Could use a SymbolFlags and "don't do anything unless SymbolFlags is an alias.
    • Clear that we need to fix the performance issue.
  • Conclusion: direction seems good, just need to make sure it's fast.

Optional Chaining with Non-Null Assertions

#36031

  • What is the intended behavior?
    • Depends on the intent?
    • a?.b!.c currently means (a?.b!).c which breaks the optional chain.
    • Could imagine that ! is allowed as part of a chain, and is fully erased to a?.b.c.
  • We'd have to change how we parse to allow postfix ! in a chain.
    • Both this case and element accesses.
  • Weird that parens do something different for other type assertions: (a?.b as Foo).c.
  • Conclusion: approved new behavior - is a breaking change though!

Variance Measurements

#32674
#32608

  • Observing different behaviors between errors reported on concrete types vs. conditional types.
  • We measure conditional types as invariant in the extends position (the right side of the extends).
    • We really don't know at the higher-order what they might do.
    • The "right" thing to do is to mark them as unmeasurable.
    • Making things "unmeasurable" means you need to do deep comparisons.
      • If you did that, and had a type Foo<T>, and T is used in the extends position (the right side of the extends), then every instantiation of Foo needs to be compared structurally.
    • This means something could cause performance issues.
  • Unmeasurable is more accurate, but slower.
  • Invariant is less complete, but is faster.
  • Will this matter?
    • People started hitting similar issues with mapped types, and we fixed it by adding unmeasurable variance markers.

The promised T Type

#35998

  • Why is this needed?

    async function foo<T>(x: T) { return await x; }
    
    foo(Promise.resolve(100)); // has type 'Promise<Promise<T>>' - wrong!
    • If awaited T was a thing, foo would return awaited T, and when instantiated, would result in Promise<number>.
  • We started out talking about this in Adds 'awaited' type to better handle promise resolution and await #17077, but we said that it would be bad to special-case this behavior.

    • Said we wanted to make a more generalized construct beyond just Promises
    • The conditional type approach didn't work.
      • Recursion limits.
      • Weird issues with Promise assimilation.
      • Assignability doesn't work well.
  • There's now a bunch of PRs that try to model Promise.all, Promise.any, and Promise.allSettled.

  • But this is a whole new other kind of type.

    • Also have to describe differences between conditional type relations vs. relations against this type.
  • What's the problem with Promise.all?

    • Today, `Promise.all((null! as Promise, null! as
    • (@rbuckton please come back to this)
  • Is this a breaking change?

    • An async function that returns the element access of a generic type, and we used to return the element type - now it's awaited T[K].
    • RWC?
      • Haven't tried.
  • Why is this urgent?

  • Conclusion: need to assess community impact - RWC and DefinitelyTyped.

@jack-williams
Copy link
Collaborator

Variance Measurements

There is a long-running PR open to fix this (#31277) which is blocked by the lack of type relationships necessary to support structural checking for conditional types. Perf could be an issue, but as it stands, I think the main concern is the breaks it will introduce without additional changes.

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