You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
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.
classBase{foo(){returnthis;}}classDerivedextendsBase{bar(){returnthis;}}vard=newDerived();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.:
classC{doSomething(other: this){varc: C;c=other;// OKother=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.:
classC{staticcreate(){returnnewthis();}}classDextendsC{}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:
classC{staticx : this;// this is the constructory: 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:
interfaceA{foo();}interfaceB{bar(): this;}varx: 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.:
functioncompare<thisextendsA>(other: this){}
Also, add a new flag --noImplicitThis to make it an error to reference this in function declarations without declaring its type.
The text was updated successfully, but these errors were encountered:
Agenda
Notes
Publishing Notes on github
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.
Design overview
Consider every class/interface as a generic type with an implicit
this
type arguments. Thethis
type parameter is constrained to the type, i.e.A<this extends A<A>>
. The type of the valuethis
inside a class or an interface is the generic type parameterthis
. Every reference to class/interface A outside the class is a type reference toA<this: A>
. assignment compatibility flows normally like other generic type parameters, e.g.: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
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.sealed
class as a way to opt-out of the newthis
Possible optimizations
interfaces: if the interface does not reference
this
anywhere explicitly in the declaration no need to instantiate. one caviet, base interfaces may referencethis
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
Discussion
this
vs.typeof this
Two options, either use
this
in a type position to indicate thethis
type, or usetypeof 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 writethis
does not existtypeof this
a lot, so saving the 7 additional characters matterthis
and expand it later to include functions declarations than to restrict the use oftypeof this
.Where is the type of this allowed
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.:
On the other hand, it is confusing to have the same notation to mean two different things, e.g:
this
and intersection typesIntersecting two types there is no effect on the value of
this
, e.g: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.:Also, add a new flag
--noImplicitThis
to make it an error to reference this in function declarations without declaring its type.The text was updated successfully, but these errors were encountered: