Skip to content

Error inheriting class B from class A that contains a method that takes a parameter of type B and returns this when decorated with multiple mixins #42383

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

Open
AlmostBearded opened this issue Jan 17, 2021 · 1 comment
Labels
Bug A bug in TypeScript
Milestone

Comments

@AlmostBearded
Copy link

Bug Report

I'm sorry for the long title but the issue is not easy to translate into words. Let me start a minimal code example.

type Constructor<T = {}> = new (...args: any[]) => T;

class A {
  foo(b: B): this {
    return this;
  }
}

function MixinA<T extends Constructor<A>>(Base: T) {
  return class MixinA extends Base {};
}

function MixinB<T extends Constructor<A>>(Base: T) {
  return class MixinB extends Base {};
}

class B extends MixinB(MixinA(A)) {}  // ERROR 

The error that's being given is: Type 'B' recursively references itself as a base type

In my opinion this error doesn't make sense or am I mistaken? The error disappears when I
a) remove the use of class B from the foo method
b) remove the this return type from the foo method
c) Only decorate class A with 1 mixin. For some reason the error disappears when only one mixin is used.
d) change the required mixin constructor type to any: function MixinA<T extends Constructor<any>>(...) {...}

The first 2 options are not viable as they are incompatible with my use case and option d looses type safety within the mixin implementations.

🔎 Search Terms

mixins recursively references itself

🕗 Version & Regression Information

When testing in the playground it seems like this error occurred between versions 3.6.2 and 3.7.5

⏯ Playground Link

Playground link with relevant code

💻 Code

type Constructor<T = {}> = new (...args: any[]) => T;

class A {
  foo(b: B): this {
    return this;
  }
}

function MixinA<T extends Constructor<A>>(Base: T) {
  return class MixinA extends Base {};
}

function MixinB<T extends Constructor<A>>(Base: T) {
  return class MixinB extends Base {};
}

class B extends MixinB(MixinA(A)) {}  // ERROR 

🙁 Actual behavior

Error Type 'B' recursively references itself as a base type. ts(2310)

🙂 Expected behavior

No error

@AlmostBearded AlmostBearded changed the title Error inheriting class B from class A decorated with nested mixins and class A contains a method that takes parameter of type B and returns this Error inheriting class B from class A that contains a method that takes parameter of type B and returns this when decorated with multiple mixins Jan 17, 2021
@AlmostBearded AlmostBearded changed the title Error inheriting class B from class A that contains a method that takes parameter of type B and returns this when decorated with multiple mixins Error inheriting class B from class A that contains a method that takes a parameter of type B and returns this when decorated with multiple mixins Jan 17, 2021
@RyanCavanaugh RyanCavanaugh added the Bug A bug in TypeScript label Jan 20, 2021
@RyanCavanaugh RyanCavanaugh added this to the Backlog milestone Jan 20, 2021
@RyanCavanaugh
Copy link
Member

This is a true type circularity, but one that we are normally able to handle, so it's weird that this is happening

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Bug A bug in TypeScript
Projects
None yet
Development

No branches or pull requests

2 participants