Skip to content

Type 'this'??? #9063

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
electricessence opened this issue Jun 9, 2016 · 14 comments
Closed

Type 'this'??? #9063

electricessence opened this issue Jun 9, 2016 · 14 comments
Labels
Question An issue which isn't directly actionable in code

Comments

@electricessence
Copy link

Is there any magic (without insane generics) to define a type that matches 'this'?

For example...

class A {
  me():A {
     return this;
  }
}

class B extends A {
  otherThing():void{}
  me():B {
    return this;
  }
}

Instead of overriding me() can I define a type without adding another generic declaration that simply solves the type of me()?

@mhegazy
Copy link
Contributor

mhegazy commented Jun 9, 2016

this?

class A {
  me(): this {
     return this;
  }
}

@DanielRosenwasser DanielRosenwasser added the Question An issue which isn't directly actionable in code label Jun 9, 2016
@electricessence
Copy link
Author

So I tried that and it started to unravel when I got into sub classes...
I want 'this' as a type to reflect the current type... Is that what : this is doing?

@mhegazy
Copy link
Contributor

mhegazy commented Jun 10, 2016

What do you mean by "current type"; and what happened with subclasses when you used this?

@basarat
Copy link
Contributor

basarat commented Jun 10, 2016

I want 'this' as a type to reflect the current type... Is that what : this is doing?

Yes.

class A {
  me():this {
     return this;
  }
}

class B extends A {
  otherThing():void{}
  me():this {
    return this;
  }
}

let a = new A, b= new B();
let foo = a.me(); // foo:A
let bar = b.me(); // bar:B

You can hover over foo / bar in your IDE to see the inferred type 🌹

@basarat
Copy link
Contributor

basarat commented Jun 10, 2016

Also, you don't need to override it i.e. the base case me function is enough 🌹

class A {
  me():this {
     return this;
  }
}

class B extends A {
  otherThing():void{}  
}

let a = new A, b= new B();
let foo = a.me(); // foo:A
let bar = b.me(); // bar:B

@mhegazy
Copy link
Contributor

mhegazy commented Jun 10, 2016

also, this types are infered automatically for you:

class A {
  me() {
     return this; // infers type this
  }
}

@electricessence
Copy link
Author

Hey thanks guys! I'm gonna check this out. It may make a huge difference in some of my class structures. I did try and do this out of instinct, but it didn't work right on my first try. I'll get back to you. ;)

@electricessence
Copy link
Author

Ok so here's where it get's sticky...

class A<T> {
  me():this {
     return this;
  }
}

class B<T> extends A<T> {
  otherThing():void{}  
}

class C<T> extends B<T> {
  map<TResult>(t:(v:T)=>TResult):this<TResult> {}
}

Anything that will make this work? :/

@basarat
Copy link
Contributor

basarat commented Jun 11, 2016

Minor simplification of your code (that still errors):

class A<T> {
    map<TResult>(mapper: (v: T) => TResult): this<TResult>{

    }
}

However this really is whatever calls the function generics and all, so I don't see a way to declare what you want 🌹

@electricessence
Copy link
Author

electricessence commented Jun 11, 2016

Yes, you get it.
Ok so it means that I have to override the function.

So lastly is there any consequences to doing something like:

class A<T> {
    clone():this {
       return new A<T>();
    }
}

@basarat
Copy link
Contributor

basarat commented Jun 11, 2016

So lastly is there any consequences to doing something like:

If a child class B fails to override it then the compiler will think new B().clone() to be B but it will really be A 🌹

@electricessence
Copy link
Author

electricessence commented Jun 11, 2016

Ok so assuming that it the type returned always matches correctly, then ok right?
Because right now, for the above sample I have to force the return like this (to get it to compile):

class A<T> {
    clone():this {
       return <any> new A<T>();  // without <any> it complains.
    }
   me():this {
      return this; // doesn't complain
   }
}

@electricessence
Copy link
Author

So I got everything to compile.

@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
Question An issue which isn't directly actionable in code
Projects
None yet
Development

No branches or pull requests

4 participants