Skip to content

Design Meeting Notes, 3/3/2023 #53083

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

Closed
DanielRosenwasser opened this issue Mar 3, 2023 · 1 comment
Closed

Design Meeting Notes, 3/3/2023 #53083

DanielRosenwasser opened this issue Mar 3, 2023 · 1 comment
Labels
Design Notes Notes from our design meetings

Comments

@DanielRosenwasser
Copy link
Member

DanielRosenwasser commented Mar 3, 2023

Check for Strict Subtyping and Fall Back to Regular Subtyping in getNarrowedType

#52984

  • Type guard affects type of variable in surprising way #50916

    • User-defined type-guards kept building up bigger and bigger types.
    • One issue - UDTG use the "regular" subtype reduction.
    • unknown should narrow to the asserted type.
    • What about any array where the type guard says "this array is an array of {}?
      • Want to keep the original type.
  • This definitely comes up with index signatures, any vs. unknown.

  • Strict subtype relationship aims to create a partial ordering among types.

  • If you end up with mutual subtypes, then at the "join points" of control flow analysis you will possibly lose the original type.

  • We did have to fix a few things in strict-subtyping in 5.0 in strict-subtype (Improvements to strictSubtypeRelation and getNarrowedType #52282)

  • Check for strict subtypes and then regular subtypes in getNarrowedType #52984

    • Ran into issue with lodash
    • isArrayLike(value: any): value is { length: number }
    • Using the asserted type only if the asserted type is a strict subtype of the original means that you can get back to the original.
      • But was too breaky.
    • In cases where neither is a strict subtype of the other, to avoid breaks, fall back to using the regular subtyping relationship.
      • Not perfect, but better than today
  • Theoretically can break this:

    type FooLike = { readonly a: string, b: string } | { c: number };
    declare function isBar(x: any): x is { a: string };
    function fn(y: FooLike) {
       if (isBar(y)) {
           y.b;
        }
    }
  • Idea: once test cases added, once reviewed, merge. Then run on top 200-300 GH repos.

  • Regardless of results, current state is pretty bad.

    • 3 individual bug reports in the last few days for 5.0.
  • Any reason why we have to "merge" instead of falling back to original type?

  • Info is lossy as to why something got narrowed.

Circularity Errors Depending on Ordering

#52813

function f() {
    const b = new Bar();
    // Changes depending on if the next line is commented.
    console.log(b.value);
}

class Bar<T> {
    num!: number;
    // Also changes depending on if this next line is commented.
    field: number = (this as Bar<any>).num;
    value = (this as Bar<any>).num;
//  ^?

//  ~~~~~ implicit any
}
  • Sometimes we hit a circularity, sometimes we don't.
    • Even with inlay hints/semantic highlighting off.
  • Get an error in the editor, but not the compiler.
  • In an editor context, the order of type-checking two files changes.
  • This is all due to variance computation.
    • Why?
      • Need to see if the this type can be related to Bar<any>.
      • Means eventually we need to see if Bar<T> is related to Bar<any>.
      • That means we need to calculate variance of the type parameters of Bar.
      • And so this variance computation means we will re-encounter Bar<T> in the resolution stack because in the editor, this might
  • Is it possible to "reset" the resolution stack when we start doing variance computations?
    • What are the implications of doing that?
    • Could get strange behavior, but worth trying.
    • But type variances can relate on other types' type variances!
      • If you reset the resolution stack, you need to keep track of when you do that.
      • "Resolution resolution stack?" 🥴😵‍💫
    • No, idea is you'd only reset the stack the first time you start computing variance.
  • It seems like we really shouldn't need to see if this is related to Bar<any>.
    • It should be "trivial" to just fetch the type of num without checking the type assertion.

    • Type resolution vs. type checking.

    • Could defer the rest of the computation?

    • Resolution could be smarter and not trigger checking.

    • Not a sufficient fix - can encounter the same issue with overload resolution issues. May not be enough.

      class Bar<T> {
          num!: number;    // Swap to remove error
          Value = callme(this).num;
          Field: number = callme(this).num;
      }
      declare function callme(x: Bar<any>): Bar<any>;
      declare function callme(x: object): string;
      • Not clear what you would defer checking here - checking and resolution is intertwined.

Octal Escape Sequences

#51837

  • Octal escape sequences are disallowed in strict mode and disallowed in ES5.
  • ES3 is deprecated now.
  • Also a perf win!
  • Need to better understand the nuances - octals, escape sequences, inside/outside of strings.
  • But we want it in TS 5.1.
@DanielRosenwasser DanielRosenwasser added the Design Notes Notes from our design meetings label Mar 3, 2023
@DanielRosenwasser DanielRosenwasser changed the title Design Meeting Notes, 3/3 Design Meeting Notes, 3/3/2023 Mar 3, 2023
@DanielRosenwasser
Copy link
Member Author

The resolution-stack-reset PR is over at #53549

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