Skip to content

Getting recursive type errors with TS 4.3.2 when they don't happen with TS 4.2.4 #44281

Description

Bug Report

Given (this is just the smaller repro I could come up with, not real code):

const p = <T>(fn: () => T): T => {return null as any}

const Base = <T>(val: T): {new(): T} => {
  return null as any;
}

class C extends Base({
 x: p<C[]>(() => [])
}) { }

With TS 4.3.2 it gives the errors:

Type 'C' recursively references itself as a base type.ts(2310)
'C' is referenced directly or indirectly in its own base expression.ts(2506)

where as there's no such error with TS 4.2.4

If the p function parameter is changed from fn: () => T to fn: () => any or x: p<C[]>(() => []) is changed to x: p<C[]>(() => [] as any) then it does not give that error anymore.

Real impact:

This impacts a library that used to be able to do self-referenced models:

class TreeNode extends Model({ children: prop<TreeNode[]>(() => []), x: prop(0) }) {}

but with the new version it is not possible anymore

Alternative repro:

abstract class Base2 {
    abstract root() : Derived
}

class Derived extends class extends Base2 {
  root() {
    return undefined as any
  }
}
{}

🕗 Version & Regression Information

  • This changed between versions 4.2.4 and 4.3.2

⏯ Playground Link

Playground Link

Activity

  1. xaviergonz commented on May 28, 2021

    @xaviergonz
    Author

    It seems this was introduced in 4.3.0-dev.20210428 (does not happen in 4.3.0-dev.20210427).

    More specifically it seems to be introduced by the addition of this line

    7748694#diff-d9ab6589e714c71e657f601cf30ff51dfc607fc98419bf72e04f6b0fa92cc4b8R17241

    from a commit from Andrew Branch (@andrewbranch)

  2. xaviergonz commented on May 28, 2021

    @xaviergonz
    Author

    More specifically the call to getBaseTypes on this line seems to trigger some side effect that causes this:

    7748694#diff-d9ab6589e714c71e657f601cf30ff51dfc607fc98419bf72e04f6b0fa92cc4b8R20008

  3. xaviergonz commented on May 28, 2021

    @xaviergonz
    Author

    The error seems to originate in getBaseConstructorTypeOfClass <- resolveBaseTypesOfClass <- getBaseTypes <- getSingleBaseForNonAugmentingSubtype

      if (!pushTypeResolution(type, TypeSystemPropertyName.ResolvedBaseConstructorType)) {
        return errorType;
      }
    

    I don't think my knowledge is deep enough to dig any deeper :( but my super-wild guess is that the array related optimization in that commit is maybe trying to resolve the class structure earlier than before and therefore the cached versions cannot keep up with it

  4. evelant commented on May 28, 2021

    @evelant

    I think this is what's breaking my mobx-state-tree project when upgrading to TS 4.3. Not sure if this is affecting all MST projects or not but I ended up with a ton of recursive type errors after trying to update to TS 4.3.

  5. dsherret commented on May 29, 2021

    @dsherret
    Contributor

    Another example showing this bug is in #44284 (I've closed that issue in favour of this one). Just like this issue, it starts happening in 4.3.0-dev.20210428.

  6. mrgleba commented on Jun 1, 2021

    @mrgleba

    Another repro

    abstract class Base {
        abstract root() : Derived
    }
    
    class Derived extends class extends Base {
        root() {
            return undefined as any
        }
    }
    {   
    }
  7. xaviergonz commented on Jun 1, 2021

    @xaviergonz
    Author
  8. DanielRosenwasser commented on Jun 1, 2021

    @DanielRosenwasser
    Member

    Unclear if this is working as intended, but it might be a regression.

  9. xaviergonz commented on Jun 10, 2021

    @xaviergonz
    Author

    has it been decided already if it is a regression or maybe something else?

  10. colinhacks commented on Jun 12, 2021

    @colinhacks

    Not to pile on, but this has broken Zod pretty comprehensively. That said, Zod uses some pretty heinous recursive type hacks so I suppose I wouldn't be surprised if this is intentional.

  11. vladzdev commented on Jun 17, 2021

    @vladzdev

    Still happening with 4.3.3 when don't happen with 4.2.4. Playground

    image

  12. vladzdev commented on Jun 17, 2021

    @vladzdev

    Error disappearing if remove

      : A extends Uint8Array | Uint16Array | Uint32Array | Int8Array | Int16Array | Int32Array
      ? Array<number>

    but compilation time is about 10x slower than 4.2.4.

  13. xaviergonz commented on Jun 17, 2021

    @xaviergonz
    Author

    The reproduction cases are still erroring for me after updating to 4.3.3...

  14. xaviergonz commented on Jun 17, 2021

    @xaviergonz
    Author

    Actually the merged fix code is not in TS4.3.3 at all...

  15. vladzdev commented on Aug 16, 2021

    @vladzdev

    Still happening with 4.4.1-rc.

  16. vladzdev commented on Aug 31, 2021

    @vladzdev

    Anders Hejlsberg (@ahejlsberg), the issue still happening with 4.4.2. Could you reopen the issue?

  17. xaviergonz commented on Aug 31, 2021

    @xaviergonz
    Author

    I think you might have better luck if you open a new issue with a playground link to the case that gets broken. as a matter of fact the two reproductions listed in the first post have been fixed in 4.4,so your issue might be because of another reason

  18. evelant commented on Aug 31, 2021

    @evelant

    Yeah something is still wrong in 4.4.2 but I'm not certain if it's this issue. My mobx-state-tree models blow up with thousands of errors if I try to upgrade, same as 4.3. I'm still stuck on 4.2.4 for now.

  19. DanielRosenwasser commented on Aug 31, 2021

    @DanielRosenwasser
    Member

    Would you each be able to open up a separate issue with a minimal repro? In the worst-case, we'll dedupe them.

  20. vladzdev commented on Sep 1, 2021

    @vladzdev
  21. locked as resolved and limited conversation to collaborators on Oct 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

BugA bug in TypeScriptFix AvailableA PR has been opened for this issue

Type

No type

Projects

No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions