Skip to content

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

@boconnell

Description

@boconnell

πŸ”Ž 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

Metadata

Metadata

Assignees

No one assigned

    Labels

    Not a DefectThis behavior is one of several equally-correct options

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions