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 12/11/2015 #6081

Closed
DanielRosenwasser opened this issue Dec 12, 2015 · 0 comments
Closed

Design Meeting Notes for 12/11/2015 #6081

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

Comments

@DanielRosenwasser
Copy link
Member

this type guards (#5906)

  • Some unaddressed concerns in PR.

  • Differences between parameter/this type guards

  • Parameter type guards check against type of parameters

  • this type-guards tied to a signature

  • `this type-guards allowed on properties

    • Rationale for allowing on properties is we needed to allow them for get-accessors.
    • Type-compatibility
  • Narrowing logic identifies when a method gets called or a property access is performed.

  • Check for a this-type guard, which will narrow the LHS of a property access.

  • Allows an identifier or this on the LHS of the is operator.

  • A this-based type guard is assignable if the

  • boolean is assignable to this-based type guard on member.

    interface Foo {
        isVar: this is Bar
    }
    var foo: Foo;
    foo.isBar = true; // kosher
  • this type predicates for properties don't allow predicates for broader types to be assigned to predicates of more specific types.

    • But that's just an assignment of a boolean, so that should be allowed.
    • Methods seem like they should still have restrictions.
    • get accessors might make this too confusing.
      • That would mean property
  • Promoted type guards to an actual type.

    • We can now make inferences for type parameters based on type predicate types.

    • Useful for functions like filter.

      function isNumber(x: any): x is number {
          return typeof x === "number";
      }
      
      let x = [1, 2, "a", "b"];
      let y = x.filter(isNumber); // type is 'number[]'
      • It would be nice if isNumber didn't need to be declared.

        let x = [1, 2, "a", "b"];
        let y = x.filter(() => typeof x === "number"); // type is 'number[]'
    • Going off-topic.

  • Let's go back to assignability rules.

    • Aside: we can elaborate and give better errors as a result of this.
    • Parameter (identifier) predicate types will only ever show up in the return type of a method.
  • We'll need to go back and check a little more, because certain people (like myself) signed off on it before a design meeting.

Get accessors via super (#4465)

  • User wants to get value of accessor via super.value from superclass.

  • Problem is we don't distinguish between getters and property descriptors.

  • This sort-of works in ES2015, but not actually.

    class {
        value: number;
        constructor() {
            this.value = 10;
        }
    }
    
    class Derived extends Base {
        foo() {
            return super.value;
        }
    }
    • foo returns undefined.
      • Runtime looks for a property descriptor on the LHS, won't find one, so returns undefined.
  • Could write a fix to lookup if a getter exists at runtime, looks really gross.

    • But how frequently do people write super.prop without using it as a call (i.e. super.prop()).
    • It's not common, so it wouldn't be the norm.
  • In ES6, we should probably allow this.

  • Potential emit:

    class A {
        foo;
        bar() { }
    }
    
    class B extends A {
        zzz() {
            let y = super.foo;
        }
    }

    to ES2015

    class A {
        foo;
        bar() { }
    }
    
    class B extends A {
        zzz() {
            var y = (_a = Object.getOwnPropertyDescriptor(_super.prototype, 'foo'),
                a && (a.get ? _a.get.call(this) : _a.value);
            var _a;
        }
    }
    • "This isn't horrible. I mean it's awful, but not horrible."
    • But this doesn't account for if this is a instance field or a prototype field.
      • How deep down the rabbit hole do we want to go?
        • "Elbow deep"
        • "Only a couple of inches"
        • If we're not making that distinction, why not just make this throw an exception.
          • It's 10-characters fewer to make it throw, so why bother to change the behavior to throw?
          • But nobody is getting what they expect anyway.
      • Actually, it doesn't matter; this.foo doesn't check the instance.
  • What about element access syntax (i.e. super[4 + 3])?

    • Wait we found a bug while playing in the playground.
  • ES6 vs ES5

    • Should this be legal in ES6 so long as the property exists?
      • Yes.
  • What about assignment to a property on super?

    class B extends A {
        zzz() {
            super.foo = 1; // (1)
            this.foo = 1;  // (2)
        }
    }
    • (1) and (2) actually do completely different things!
      • (1) actually sets a descriptor on this (!!??)
      • ` But not
  • Resolution: 👍 (need to propose a new emit)

super should be allowed in a computed property (when nested in a class) (#6038)

  • When in a computed property, super refers to the super of the containing class.
  • We currently
  • Why is this allowed?
  • Resolution: 👍 (fix the bug)

super in object literal causes error (#5441)

  • This should work given that __proto__ is valid.
  • Should be allowed, since it's only invalid if __proto__ is set to null.
    • Should only be allowed in a method body of an object literal.
    • Should only be allowed in ES6.
  • Should we do inference on __proto__ for super?
    • Weird, we don't do any inference for this.
    • We shouldn't do it for one and not the other.
    • Revisit that down the road.
  • Resolution: 👍 (allow in ES6)

Intersection types (intersecting with string) are not valid index signature types

  • Two issues for this:

    1. Can't define a string indexer type taking an intersection with string
    2. Can't index with type intersecting with string, when indexing value has a string index signature.
      • Arguably more surprising of the two.
  • Is this useful?

    • Yes, totally, we use it in the compiler to differentiate plain strings from canonical paths.
  • We do hacks like this in the compiler to differentiate strings from actual paths.

    • Tags a value.
    • Kind of like units of measure.
    • Verification tagging in some instances.
      • Data sanitization.
  • But these types don't exist at runtime.

    • But that's fine, this has no runtime overhead instead of wrapping it in a tagging object.
  • Aside: thanks to string literal types, you can do even more crazy tagging stuff.

    type Meters = number & "Meters";
    type Feet   = number & "Feet"
    • But... that's bad because now you have methods of global Number and String types.
      • Don't do that.
  • Resolutions

    • Unsure of accepting other types in index signature parameters.
    • For accepting intersections with string when performing an element access, 👍 (someone write a proposal for this)
  • But, this is just supporting a hack, so we should really consider giving people a better mechanism.

@DanielRosenwasser DanielRosenwasser added the Design Notes Notes from our design meetings label Dec 12, 2015
@microsoft microsoft locked and limited conversation to collaborators Jun 19, 2018
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