Skip to content

TypeScript Design Notes for 9/18/2015 #4931

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
mhegazy opened this issue Sep 22, 2015 · 3 comments
Closed

TypeScript Design Notes for 9/18/2015 #4931

mhegazy opened this issue Sep 22, 2015 · 3 comments
Labels
Design Notes Notes from our design meetings

Comments

@mhegazy
Copy link
Contributor

mhegazy commented Sep 22, 2015

Agenda

Notes

Publishing Notes on github

  • Publish notes on github a la C#

Conclusion: Start publishing this meeting as github issues

Design update on this types for classes and interfaces (#3694)

Overview

This update is only limited to declaring, inferring and propagating this types in classes and interfaces. function declarations will be handled separately. With this in place, fluent APIs can be correctly modeled in TypeScript, e.g.

class Base {
     foo() {
         return this;
     }
}

class Derived extends Base {
     bar() {
         return this;
     }
}

var d = new Derived();
d.foo().bar(); // where the call to foo returns Derived and not Base.

Design overview

Consider every class/interface as a generic type with an implicit this type arguments. The this type parameter is constrained to the type, i.e. A<this extends A<A>>. The type of the value this inside a class or an interface is the generic type parameter this. Every reference to class/interface A outside the class is a type reference to A<this: A>. assignment compatibility flows normally like other generic type parameters, e.g.:

class C {
     doSomething(other: this) {
          var c: C;

         c = other; // OK
         other = c; // Error, other is not guaranteed to be a c
     }
}

Performance concerns

With this type treated as a generic type parameter, every type is generic and every reference to a type is a generic type reference that has to be instantiated. Huge perf and memory cost..

Alternatives

  • Make this type opt-in and not inferred automatically, pros: no perf penalty for existing code, cons: unintuitive, not clear when you should declare it or not, it is not clear what would be a notation on classes/interfaces to signify they need to capture this type.
  • Possibly add support for sealed class as a way to opt-out of the new this
Possible optimizations

interfaces: if the interface does not reference this anywhere explicitly in the declaration no need to instantiate. one caviet, base interfaces may reference this
classes: do not try to do this for classes, all classes would have a reference to this in a body of a method, doing the analysis to figure out if the this type "escapes" the class body is not cheep.
do the check on property/method level, e.g. if the property type is a primitive type, number,sting,etc.. no need to instantiate for this

with these optimizations in place, perf penalty can be reduced to 5% for class-heavy code bases.

Conclusion: this types adds new expressiveness to the language and enables for modeling common APIs; the feature provides enough value to offset the perf degradation.

Action item: follow up on plans to offset the perf loses by looking for other optimizations in the system

Discussion

this vs. typeof this

Two options, either use this in a type position to indicate the this type, or use typeof this instead:

  • typeof this is more consistent with other places where typeof is used, and indicates difference between value and type spaces.
  • this is shorter to write
  • in an interface the value this does not exist
  • in a fluent API, you will be typing typeof this a lot, so saving the 7 additional characters matter
  • it is easier to restrict a new type this and expand it later to include functions declarations than to restrict the use of typeof this.

Conclusion: use this to indicate type of this, in the future expand typeof to allow this

Where is the type of this allowed

  • Only in method bodies, property declaration/signature, method declaration/signature within a class or an interface
  • Not allowed in static properties or methods.

static this

A common pattern is a create method on a class, that returns the type of a subtype instead of of the type. e.g.:

class C {
    static create() {
        return new this();
    }
}

class D extends C {}

D.create(); // expect it to be D

On the other hand, it is confusing to have the same notation to mean two different things, e.g:

class C {
   static x : this; // this is the constructor
   y: this;   // this is the instance this
}

Conclusion: do not allow this in static members

this and intersection types

Intersecting two types there is no effect on the value of this, e.g:

interface A {
    foo();  
}
interface B {
    bar(): this;    
}

var x: A & B;

x.bar() // returns B and not A&B

The reason is this is a generic parameter of the type that is instantiated by the reference, (which is needed to support property declaration using type this), and not passed at the call site. This does not match the JS call semantics. but can be done along with function declaration this type support.

Function declarations

Function declarations needs to be handled separately. An explicit this type parameter would be specified, and checked for assignment compatibility. e.g.:

function compare<this extends A>(other: this) {
}

Also, add a new flag --noImplicitThis to make it an error to reference this in function declarations without declaring its type.

@mhegazy mhegazy added the Design Notes Notes from our design meetings label Sep 22, 2015
@mhegazy mhegazy closed this as completed Sep 22, 2015
@kitsonk
Copy link
Contributor

kitsonk commented Sep 23, 2015

👍 for publishing the notes! It helps all us needy demanding children understand you keep us in your thoughts.

@tinganho
Copy link
Contributor

👍 also for publishing the notes!

@jbondc
Copy link
Contributor

jbondc commented Sep 23, 2015

👍 this is fantastic, requires ☀️ 🍸 🎉 and 🏆

@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

4 participants