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/15/2021 #42416

Closed
DanielRosenwasser opened this issue Jan 20, 2021 · 0 comments
Closed

Design Meeting Notes, 1/15/2021 #42416

DanielRosenwasser opened this issue Jan 20, 2021 · 0 comments
Labels
Design Notes Notes from our design meetings

Comments

@DanielRosenwasser
Copy link
Member

Smarter Literal/Subtype Reduction

#42353

  • Imagine EnumA and EnumB which each have 1000 members.
  • If you have an array like [EnumA.Member1, EnumB.Member1, someObject], then we'll try to do subtype reduction.
  • Each enum is technically a union, with 1000 literal type members.
  • Subtype reduction is O(n2), so when we try to reduce each enum, that can end up being expensive! We have a heuristic to avoid doing this work by checking up-front if we're going to do a lot of work.
  • However, in this PR, we always start out by doing a literal type reduction pass (a pass which is way cheaper than general subtype reduction), and then do full subtype reduction.
  • We always had a literal type reduction pass, but now we always apply it in the presence of any literal types (not just all-literal types).
  • We also had this other special code to handle enums before; seems like we were able to remove them.
  • The code got smaller from this change! 🎉
  • Some...breaks.
    • We used to keep void | undefined - now we reduce it to undefined.
    • A change where we now do not reduce primitives and object types that have members in common..
      • For example, [someString, { toString(): string { return "hi" } }] doesn't reduce to just the object type.
  • Does it make sense that undefined is reduced to void? Isn't it the other way around?
    • We've always had void being a supertype of undefined.
  • Users try to cast to unknown[] or any[] or whatever, but it doesn't stop the complex computation. Could we peek at that?
    • Potentially - could just do a single assignability check to

Exploding Template String Types

`${theme.colors.grey} ${theme.colors.grey} ${theme.colors.white}`
declare var a: "a" | "whole" | "bunch" | "of" | ... | "strings";

const t = `${a} ${a} ${a}`;
  • Expands out to a very big union type.

  • If the union is too big, it can be too complex.

  • It used to be that you had to opt into template literal types with as const on template strings - now you're sort of always thrown into it.

  • Two proposals

    • One is "this thing is too big" and give a better error message, and
    • make it so that as string allows you to opt out.
  • Do we have any tests for perf?

    • Relatively new feature.
    • Well we know this is strictly never going to be faster.
  • Try to find some project that uses template strings to see what sort of regressions they have.

    • Artsy has some, we can ping them!
  • Also maybe provide a quick fix.*

  • Feels like the usual expectation is "give me a reasonable type, and I'll use as const unless I opt-in."

  • Can convince ourselves of either direction.

  • Thing that's odd about not doing this work

    const x = `somestring`; // this is a literal type
    
    const str = "string;
    const x = `some${str}`; // this is not? fishy.
  • We really should try to avoid doing the full type computation if you're contextually typed, it happens all the time.

@DanielRosenwasser DanielRosenwasser changed the title Design Meeting Notes, 1/19/2021 Design Meeting Notes, 1/15/2021 Jan 20, 2021
@DanielRosenwasser DanielRosenwasser added the Design Notes Notes from our design meetings label Jan 20, 2021
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

1 participant