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

InstanceType<(typeof this)["somefield"]> type issue #51013

Closed
imsamurai opened this issue Sep 30, 2022 · 5 comments
Closed

InstanceType<(typeof this)["somefield"]> type issue #51013

imsamurai opened this issue Sep 30, 2022 · 5 comments
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug

Comments

@imsamurai
Copy link

Hi, for inheritance purposes i need to type methods depending on class returned by getter, but i get 'is not assignable' error.
Is this a bug?

class S1 {}
class S2 extends S1 {}


class A  {
   get x() {
    return S1
  }

  f(): InstanceType<(typeof this)["x"]> {
   return new this.x as InstanceType<(typeof this)["x"]> // no error
  }

  fError(): InstanceType<(typeof this)["x"]> {
   return new this.x // got error
  }
}


class B extends A {
  get x() {
    return S2
  }

  f1(){
    return this.f();
  }
}


const a = new A;
const s1test = a.f() // S1 type


const b = new B;
const s2test = b.f1() // S2 type

https://www.typescriptlang.org/play?#code/MYGwhgzhAEDKCM0DeBfAUKSNYCZoFMAPAF3wDsATbRVNOzKaAQWmTVegHN9jpCAKAJRJ2HAE48ArmLJx4o9KIBmQgFzQAkmQjEwZYPgAqATwAO+ADzEAFgEsIAbQBEhJwF0AfG3FSZ0MvgA7tA29gB0hNCQmtq6+kZmlqGOLu5eAPTp-gD2BGJi2WIKdKxKAKL5hWoxOnoGJuZWdimunt6sEsTSsgHByRHQmVzZvPiVRazoihjgjABCBCTkVMzt3LwCgu0dvrK4xcrwQiIc0J3dIc1hKoIA3MXTwNmxUdAAvP5BzPdPLxDwpB07yi1yEgyyCBCiToGGeQIARsDetA5j84bwIDhAbwPvDrkctkNcFDzEA

@nopeless
Copy link

nopeless commented Sep 30, 2022

There are too many things wrong with this code but I'll just leave a good solution

class S1 {}
class S2 extends S1 {}

class A<X extends new (...args: any[]) => any> {
  constructor(public cls: X) {}

  get x(): X {
    return this.cls
  }

  f(): X {
    const o = new this.x()
    return o;
  }
}

class B<X extends new (...args: any[]) => any> extends A<X> {
  f1(){
    return this.f();
  }
}


const a = new A(S1);
const s1test = a.f() // S1 type
//    ^?

const b = new B(S2);
const s2test = b.f1() // S2 type
//    ^?

demo

@imsamurai
Copy link
Author

thanks, but based on current architecture (including dependency injector) i can't accept your solution.
Also, your code have error (in extends of B) and produce types, not instances (s1test/s2test)
The question is why it not work as expected

@whzx5byb
Copy link

InstanceType<(typeof this)["x"]>(or InstanceType<this["x"]) is a deferred conditional type, and S1 cannot be assignable to it because of #46429.

Personally I'll suggest avoid using conditional types as return type of a function, in your case you could use this['x']['prototype'].

@nopeless
Copy link

nopeless commented Sep 30, 2022

thanks, but based on current architecture (including dependency injector) i can't accept your solution. Also, your code have error (in extends of B) and produce types, not instances (s1test/s2test) The question is why it not work as expected

@imsamurai
You are correct

Here is the one that correctly returns the type

class S1 {}
class S2 extends S1 {}

class A<X extends new (...args: any[]) => any> {
  constructor(public cls: X) {}

  get x(): X {
    return this.cls
  }

  f(): InstanceType<X> {
    return new this.x();
  }
}

class B<X extends new (...args: any[]) => any> extends A<X> {
  f1(){
    return this.f();
  }
}


const a = new A(S1);
const s1test = a.f() // S1 type
//    ^?

const b = new B(S2);
const s2test = b.f1() // S2 type
//    ^?

demo

@RyanCavanaugh RyanCavanaugh added the Working as Intended The behavior described is the intended behavior; this is not a bug label Sep 30, 2022
@typescript-bot
Copy link
Collaborator

This issue has been marked 'Working as Intended' and has seen no recent activity. It has been automatically closed for house-keeping purposes.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Working as Intended The behavior described is the intended behavior; this is not a bug
Projects
None yet
Development

No branches or pull requests

5 participants