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 for 2/05/2016 #6930

Closed
DanielRosenwasser opened this issue Feb 5, 2016 · 0 comments
Closed

Design Meeting Notes for 2/05/2016 #6930

DanielRosenwasser opened this issue Feb 5, 2016 · 0 comments
Labels
Design Notes Notes from our design meetings

Comments

@DanielRosenwasser
Copy link
Member

Joke of the day

  • Anders: "What do you call a fish without an eye?"
    • "Fsh!"

Breaking Changes

"use strict" changes for modules (#3676)

  • Requested by several people.
  • Broke several people.
  • New flag
  • Yay, new flags!
  • Today's flag is...
    • emitNonStrictModules.
    • Keeps compliance, but allows people to revert behavior.
    • Do we emit "use strict" for classes?
      • No.
      • We should.
      • Should this flag affect that when we make that change?
        • Yes, let's give the flag a better name to reflect that.
      • Would we be breaking people if we actually did this though?
        • Apparently yes.

Defaulting to built-in promises

  • We used to use type annotations as a guide to enable a bring-your-own-promise scenario.
    • Doesn't match with semantics reflecting original spec.
    • Breaks design goals.
  • Could we remove the restriction for ES6 (ES7?) and prior?
    • Sure?
  • Options:
    • Keep breaking change
    • Undo the change, perform the breaking change when we actually have downlevel async/await.
  • Resolution: undo the change, apply it when we actually allow users to downlevel their async code.

Features (and potential breaking changes)

Specifying this types for functions (#6739)

  • What does the "strict this" world look like?

  • We will check this just as if it was an argument today.

  • Consider

    class Foo {
        m() {
            this.blah();
            // ...
        }
    
        blah() {
            // ...
        }
    }
    
    let foo: Foo;
    let e: () => void = foo.m;
    e();
    • That example will crash because m has been orphaned from its Foo instance.
  • Strict this-checking aims to fix this issue.

  • this appears in the parameter list for functions and function types.

  • this types affect assignability of signatures:

    type EventA = (this: Element, x: string) => void;
    
    type EventB = (this: void, x: string) => void;
    
    let a: EventA;
    let b: EventB;
    
    a = b; // Error: 'void' isn't enough for a method needing an 'Element' for 'this'.
    b = a; // Okay: No problem with getting *more* than you expect.
    • Assignability is still bivariant for a this parameter
  • In strict-this mode, the following's an error:

    function foo(s: string) {
        this.abc; // Error: 'this' is implicitly a 'void'.
    }
  • Arrow functions will always hold the value of this from their containing scope.

  • Free-standing functions implicitly get a void type for this.

  • Methods in classes implicitly have a this type of this.

    • Hopefully this is not very surprising.
    • This prevents incorrectly "ripping off the method" (this orphaning) from the first example.
  • Static methods have a this type of typeof Foo where Foo is the containing class.

  • Does this fix the bind function?

    • Almost!!
  • Why do we need a flag?

    • It breaks existing code for when your methods have no dependency on this.

    • Occurs several types in the compiler.

    • Problems sprout up between methods signatures and function type literals:

      interface Foo {
          a(): void;
          b(): void;
      }
      
      interface Bar {
          a: () => void;
          b: () => void;
      }
      • Foo methods implicitly get a this: this type, while Bar methods get a this: void type!
      • We need to be prescriptive and explain to people how to write definitions.
      • People are still going to run into such gotchas.
  • By default, without the strict-this flag, there will be no implied this type.

  • But we still want contextual typing to work correctly:

    addOnClick(function (e) {
        // 'this' has the 'Element' type.
        this./*|*/
        //     |
        //     +-- Members of the 'Element' type.
    });
  • What about object literals?

    • If the object is contextually typed by X, methods will get the this type of X.

      var o: X = {
          x: 10,
          m() {
              this // has type 'X'
          }
      }
    • An object literal with no contextual type just grabs the type of the object literal:

      var o: X = {
          x: 10,
          m() {
              this // has type '{ x: number; m(this: /*typeof o?*/); }}'
          }
      }
      • Uh-oh, how will the declaration emitter and language-service print the type of o?
  • Speaking of surfacing the representation of these types...

    interface Foo {
        bar();
    }
    // What is the type of 'foo'? (this: this) => void?
    const foo = foo.bar;
  • So are all these very big changes going to need these sorts of flags?

    • Are we going to have a "very strict mode"?
  • Do overload this parameters need to match?

    • No.

Unique types/tagged types/opaque types

  • People keep asking for this.

  • Ideas from last time:

    unique class C {
        // ...
    }
    
    unique interface I {
        // ...
    }
    
    unique type Path = string;
  • The biggest question last time was what the behavior was for the type alias example (i.e. Path).

  • We're thinking that

    type Path = string & (unique {});
    • We can also do some stuff so that Path will be printed as Path.
  • This approach, combined with intersections, allows you to "compose" on existing types.

  • You can write Path & Lowercased.

  • Unique interfaces are useful for preventing people from forging nodes.

  • What about if a base is unique?

  • Does unique affect the static side?

    • Maybe?
    • Actually, you get that for free because the constructor function returns a unique type.
    • Well almost. But that would require a type assertion anyhow.
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Design Notes Notes from our design meetings
Projects
None yet
Development

No branches or pull requests

1 participant