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
{{ message }}
Repository navigation
Allow type system to represent this in function inputs/outputs #285
The early discussions about generics had this feature outlined, but it never made it into the final version for some reason. Meanwhile, it would be extremely helpful in some cases. The use case that it most dear to my heart is Knockout:
interface Observable<T> {
<U>( this: U, value: T ): U;
}
var viewModel = {
Str: ko.observable( "abc" ),
Num: ko.observable( 5 )
};
viewModel.Str( "xyz" ).Num( 10 );
How different is this from #229? If 'this' was allowed as a parameter type we could also look at allowing it as a return type to accomplish what you want here? Ex, Basarat Ali Syed (@basarat)'s example without generics:
Dan Quirk (@danquirk) that issue is more focused on thisinside the function. This issue is focused on this outside the function (i.e. return value or inputs). Also putting it in generic arguments allows you to restrict the type with extends e.g. this T extends Base:
Basarat Ali Syed (@basarat) right, but if we go as far as Ryan Cavanaugh (@RyanCavanaugh) suggests in that issue and consider how it affects assignability with function types then allowing it to be used in other signature positions for assignability is likely a small additional step.
suggests in that issue and consider how it affects assignability with function types then allowing it to be used in other signature positions for assignability is likely a small additional step.
There are two very different suggestions going on here that I don't want to conflate.
The first is whether or not you can accurately represent clone-type operations:
functioncreateClone<T>(t: T): T{returnt;/* TODO: science! */}classAnimal{clone(): this {returncreateClone(this);}// ~~~~ }classDogextendsAnimal{woof(): void{}}varx=newDog();x.clone().woof();// Should not error; `clone` currently returns `Animal` and causes error
The other issue is the type of this inside a function body:
$('li').each(function(){// http://api.jquery.com/each/console.log(this.nane);// Should be an error~~~~typeof'this'shouldbeHTMLElementhere});
changed the title [-]Allow type system to represent `this` as a function type[/-][+]Allow type system to represent `this` in function inputs/outputs[/+]on Jul 30, 2014
I'm pretty sure that we on the team understand it, but let me just be clear on the fact that allowing this-typing on a parameter is not actually type safe.
Consider the following:
classA{a: number;// This would *clearly* be the ideal usage of 'this'-types as a parameter.compare(other: this): boolean{returnthis.a===other.a;}}classBextendsA{b: number;// Now override A's 'compare'.compare(other: this): boolean{returnthis.b===other.b;}}vara1: A=newA();vara2: A=newB();a2.compare(a1);
So this would fully type check, but a2's type at runtime is actually B, and a2.compare will try to access a1.b which doesn't actually exist.
So really, I'd prefer that if we ever did this, we restricted this as a return type.
It seems that it can be a problem even without this-typing. This code is basically same with yours and does not cause any compiler error.
classA{a=1;// default// This would *clearly* be the ideal usage of 'this'-types as a parameter.compare(other: A): boolean{returnthis.a===other.a;}}classBextendsA{b=2;// default// Now override A's 'compare'.compare(other: B): boolean{if(!("b"inthis)||!("b"inother))thrownewError("It seems there is an error...");returnthis.b===other.b;}}vara1: A=newA();vara2: A=newB();a2.compare(a1);// This still throws a runtime error but not a compile-time error.
I don't think that example is coherent either way, since B behaviorally breaks the substitution principle. It's not correct for it to subclass A and add exception cases to compare.
Daniel Rosenwasser (@DanielRosenwasser) Only allowing this for return types is still very useful. I'd say it's entirely justifiable as long as the compiler outputs a decent error message when trying to use it elsewhere.
I would propose the keyword to be This, with capital T, just to differentiate it from the property this.
Any news on when this feature might land in a stable release?
Hey Brandon Luong (@bluong), I think we're still interested in it, but ES6 work has dominated much of our time. We're still also lacking a solid proposal.
I'd love to see this as a return type for chaining methods implemented - it would greatly improve the node.js type definitions, which currently don't support things like:
readStream.on('error', ...).pipe(writeStream);
The biggest issue for this as a return type is inheritance - chaining methods need to be differentiated from clone-like. My suggestion would be to implement this as a return for chaining methods first, e.g.
classChainer{doSomething(...) : this {// do somethingreturnthis;}}
Classes with chaining methods can be safely inherited from while maintaining this as the return type. So any methods specifying this as a return type need to return this and nothing else.
For clone-like methods maybe a generic this<T> would work to show that the particular implementation returns T, so must be overridden in derived classes.
It should be possible for these return types to be used to override each other, as well as specifying the base class or derived class as the return type (instead of this).
Martin Reinhardt (@hypery2k) the most recent proposal is #3694. We have a few different issues tracking the various ways people want to specify this types. Suffice to say we know it's a top request but it's also complicated to support correctly :)
Activity
basarat commentedon Jul 28, 2014
Use case ported :
With
this:Syntax is up for debate. But I believe
thisshould be at the generic argument list location.danquirk commentedon Jul 29, 2014
How different is this from #229? If 'this' was allowed as a parameter type we could also look at allowing it as a return type to accomplish what you want here? Ex, Basarat Ali Syed (@basarat)'s example without generics:
Bartvds commentedon Jul 29, 2014
+1 for
thisas type, it would solve some problems of writing 'chainy' API's, and with clean and semantic syntax.It wouldn't solve #229 or the OP, which are more for callbacks and handlers with changed scope.
fsoikin commentedon Jul 29, 2014
This is not different from #229 at all (as far as I can see).
I must, however, note that the example in your comment is needlessly narrowed to a special case. I would rewrite it something like this:
fsoikin commentedon Jul 29, 2014
Forgot to add an opposite example:
basarat commentedon Jul 30, 2014
Dan Quirk (@danquirk) that issue is more focused on
thisinside the function. This issue is focused onthisoutside the function (i.e. return value or inputs). Also putting it in generic arguments allows you to restrict the type withextendse.g.this T extends Base:For a demo of function input consider
mergebelow (probably not a good example).danquirk commentedon Jul 30, 2014
Basarat Ali Syed (@basarat) right, but if we go as far as Ryan Cavanaugh (@RyanCavanaugh) suggests in that issue and consider how it affects assignability with function types then allowing it to be used in other signature positions for assignability is likely a small additional step.
basarat commentedon Jul 30, 2014
Dan Quirk (@danquirk) agreed this can be marked a duplicate 👍
RyanCavanaugh commentedon Jul 30, 2014
There are two very different suggestions going on here that I don't want to conflate.
The first is whether or not you can accurately represent
clone-type operations:The other issue is the type of
thisinside a function body:[-]Suggestion: generic 'this' argument[/-][+]Allow type system to represent `this` as a function type[/+][-]Allow type system to represent `this` as a function type[/-][+]Allow type system to represent `this` in function inputs/outputs[/+]DanielRosenwasser commentedon Dec 26, 2014
I'm pretty sure that we on the team understand it, but let me just be clear on the fact that allowing
this-typing on a parameter is not actually type safe.Consider the following:
So this would fully type check, but
a2's type at runtime is actuallyB, anda2.comparewill try to accessa1.bwhich doesn't actually exist.So really, I'd prefer that if we ever did this, we restricted
thisas a return type.saschanaz commentedon Dec 26, 2014
It seems that it can be a problem even without
this-typing. This code is basically same with yours and does not cause any compiler error.RyanCavanaugh commentedon Dec 30, 2014
I don't think that example is coherent either way, since
Bbehaviorally breaks the substitution principle. It's not correct for it to subclassAand add exception cases tocompare.nathggns commentedon Feb 10, 2015
Defining the type of
thiswithin a function body is covered by #1985emanuelpalm commentedon Apr 10, 2015
Daniel Rosenwasser (@DanielRosenwasser) Only allowing
thisfor return types is still very useful. I'd say it's entirely justifiable as long as the compiler outputs a decent error message when trying to use it elsewhere.I would propose the keyword to be
This, with capital T, just to differentiate it from the propertythis.Any news on when this feature might land in a stable release?
bluong commentedon May 18, 2015
Would very much like an update into this issue
DanielRosenwasser commentedon May 18, 2015
Hey Brandon Luong (@bluong), I think we're still interested in it, but ES6 work has dominated much of our time. We're still also lacking a solid proposal.
pmccloghrylaing commentedon May 20, 2015
I'd love to see
thisas a return type for chaining methods implemented - it would greatly improve the node.js type definitions, which currently don't support things like:The biggest issue for
thisas a return type is inheritance - chaining methods need to be differentiated fromclone-like. My suggestion would be to implementthisas a return for chaining methods first, e.g.Classes with chaining methods can be safely inherited from while maintaining
thisas the return type. So any methods specifyingthisas a return type need toreturn thisand nothing else.For
clone-like methods maybe a genericthis<T>would work to show that the particular implementation returnsT, so must be overridden in derived classes.It should be possible for these return types to be used to override each other, as well as specifying the base class or derived class as the return type (instead of
this).hypery2k commentedon Aug 6, 2015
any news on this issue?
danquirk commentedon Aug 6, 2015
Martin Reinhardt (@hypery2k) the most recent proposal is #3694. We have a few different issues tracking the various ways people want to specify
thistypes. Suffice to say we know it's a top request but it's also complicated to support correctly :)DmitryEfimenko commentedon Sep 13, 2015
+1
mhegazy commentedon Sep 16, 2015
this is now tracked by #3694