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

Inheriting from 21 combined mixins causes "type instantiation is excessively deep and possibly infinite" #59659

Closed
boconnell opened this issue Aug 16, 2024 · 5 comments
Labels
Not a Defect This behavior is one of several equally-correct options

Comments

@boconnell
Copy link

boconnell commented Aug 16, 2024

πŸ”Ž Search Terms

Mixin mixins 20 21 type instantiation is excessively deep and possibly infinite

πŸ•— Version & Regression Information

  • This is the behavior in every version I tried, and I reviewed the FAQ for entries about _________

⏯ Playground Link

https://www.typescriptlang.org/play/?#code/IYIwzgLgTsDGEAJYBthjAgQmgpgeRACsEBvAKAUqQHsA7SKAV3mqgAoA6L4KAczABcCYLQCeAbQC6ASlIBfMgrIUEAM0a14ASzoIAKjC0QADADEAPHuxgcCHAA8IOWgBMMEUQAcc1VVlwEhAB8bNY4Qla40uRUwuDQcIgoaBgGwEbGdo7Obv428iqUUDgQjFC0+oYmKkoq6poQOhVpRgCMFpH5Dk6u7l4+fmGBIWERYdGFcQyJSKjolekQrVk9uWEFscWl5QttNcp1Gtq6LRAATB3r3Tl93r55+EQjuGNRMVSg0-CzKbvnKzcHhsqFsys0qmd9spKPVjuDFgBmS64AG9BAeO6DAJPUIvfTjd6UT4Jb7JeanBGotYokgKTYlMF-BFQw4NJp-AAsyK62TRGIGD2GuJsrxsE1ixJgpLmqSqHKpGHWtMmoJ2pw5LJhR0aJyqAFZubZrnz+vchjjRvi3pNJTMybLFnqFUDlfTtvCjHrNWptezTgA2Q3O-lm7HBYXhK1iwlTElJGV-f3OpV0kEMtVVf3e2E6j0QADsQeNuRDWJsQstnRw4o+8Sl8d+p3zyZpqaK6bz+ezvt1iwAHEXeSXTWXHuHKwSbXW7QnTn2W-lXWn3X8+922b2jABOQerW4C83jvFVmtE6fSxtVLcL2xL9sr05b9dwv6tMyWK5D-eh8sW4+TiVzwbckqjfG9gXvRlTjfZ9c1fdoPxRYtv1HCt-2tQCvmAh02mWZCXTbBBVTzVpWlgv1QIuRCeT3dER0FP8RSjasY1tC8QMWVoznAu8iI7V9IUoWotQ3EikWoo0vzozEGKPJiT1YoCfg4tpKXwlMVX46DmSEg4RJfaCuQk4N6MPZ55IA2ssOUnClnldTW00h9QI1XToR9UTXwNYz8NLWTzMjBSp2s+0vJ4wjiK88jNyWQMfKkvyzIjUUWOCuMbNfJMHMXCKtNArM3NZAzQMLeLaMSsMApS09Y3rDLoObbLb1y5zOK7Qr9Lg6CBzKwEKt-OTAsss8QtnUD5yaiC+Nato1w6jzis4ndepNGSkonDCrPS0LoOvSbeMi3borzM53yrEy1sq5LmJqtjsL+U7wqcqCIWMY6HoQ87fNMq6NujNK6p2iE8KkjS3RexYzjItzYDoSAEAAYToWAthwdYAF4PtMNhTlO7Hdvx8bCba4m2kDHHQINCnOK5anVNJpYLjppZ2mZt8GZ3ZmB2ZwtmfJ04qfVBmkWZpnoIZswI0CaQZdluX5YV6QAG5lFCpHNFRhGAAstGQFxnXVlGSjR1sgA

πŸ’» Code

abstract class BaseObj {
    constructor(...args: any[]) {}
}


  function Trait0F<TBase extends typeof BaseObj>(Base: TBase){
    abstract class Trait0 extends Base {}
    return Trait0
  }


  function Trait1F<TBase extends typeof BaseObj>(Base: TBase){
    abstract class Trait1 extends Base {}
    return Trait1
  }

// ...


  function Trait21F<TBase extends typeof BaseObj>(Base: TBase){
    abstract class Trait21 extends Base {}
    return Trait21
  }

const ConcreteBase = Trait21F(Trait20F(Trait19F(Trait18F(Trait17F(Trait16F(Trait15F(Trait14F(Trait13F(Trait12F(Trait11F(Trait10F(Trait9F(Trait8F(Trait7F(Trait6F(Trait5F(Trait4F(Trait3F(Trait2F(Trait1F(Trait0F(BaseObj)))))))))))))))))))))); // excessively deep

class ConcreteChild extends ConcreteBase {}

πŸ™ Actual behavior

The line with Trait21F(...) where we assign to ConcreteBase throws the "type instantiation is excessively deep" error. The error goes away if there is at most 20 mixins (e.g. the last one is Trait19F), so any number more than 20 seems to be the problem.

It's worth noting that if for every trait we had a static class e.g. class Trait0 extends Trait0F(BaseObj) and then intersected them all together, e.g. const ConcreteBase = typeof Trait21 & ... & typeof Trait0 & typeof BaseObj that everything works (TS playground), which feels like it should be functionally equivalent.

Expressing this the manual way, by having the equivalent trait classes extend each other statically (class Trait1 extends Trait0 etc...), also works: TS Playground

πŸ™‚ Expected behavior

I would expect this to not error. This recursion isn't infinite and doesn't seem like it would exceed the depth limit of 100 currently hard-coded into the compiler, and in general the 2 alternatives which work should be equivalent.

Additional information about the issue

Related:
#34933
#54533

@boconnell
Copy link
Author

boconnell commented Aug 16, 2024

OK checked more versions and this is technically a regression from version 3.5.1.

@RyanCavanaugh
Copy link
Member

I would expect this to not error. This recursion isn't infinite

The error message says "excessively deep" and, yeah, a 20-deep function call qualifies as "too deep" for the purposes of not crashing/hanging in other codebases. You'll need to use a workaround.

@RyanCavanaugh RyanCavanaugh added the Not a Defect This behavior is one of several equally-correct options label Aug 16, 2024
@boconnell
Copy link
Author

boconnell commented Aug 16, 2024

This is not strictly about function depth though. If you annotate the functions with return types, the error goes away: TS playground.

As I mentioned before, this basically flattens out to static class extension, which is also fine.

This feels like something to do with either inference and/or the mixin code path, as the problem does not apply more generally.

@typescript-bot
Copy link
Collaborator

This issue has been marked as "Not a Defect" and has seen no recent activity. It has been automatically closed for house-keeping purposes.

@typescript-bot typescript-bot closed this as not planned Won't fix, can't repro, duplicate, stale Aug 19, 2024
@avetisk
Copy link

avetisk commented Aug 19, 2024

@RyanCavanaugh is there a way to locally increase the max depth?

Because sometimes with complex concepts, we really need a lot of depth.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Not a Defect This behavior is one of several equally-correct options
Projects
None yet
Development

No branches or pull requests

4 participants