0

I am generating TypeScript code that contains errors. In order to generate the right code, I need to understand what is going on in the following examples:

What is the reason that the following code snippet results in a 'circular reference' error:

type Dict<T> = { [key:string]: T }

export namespace X {

    export type A<T> =
        | ['em', X.B<T>] //<-- error on this line


    export type B<T> = Dict<X.A<T>> //<-- and error on this line
}

but if I remove the reference to the namespace, there's no problem:

type Dict<T> = { [key:string]: T }

export namespace Y {

    export type A<T> =
        | ['em', B<T>] //<----


    export type B<T> = Dict<X.A<T>>
}

and also if I remove the type parameter there is no issue:

type Dict<T> = { [key:string]: T }

export namespace Z {

    export type A =
        | ['em', Z.B]


    export type B = Dict<Z.A>
}
Corno
  • 5,448
  • 4
  • 25
  • 41
  • It looks like a bug to me. If you don't use the leading pipe ([which is meant to be ignored](https://github.com/microsoft/TypeScript/pull/12386)) [it works](https://www.typescriptlang.org/play?#code/C4TwDgpgBAIglgY2AHgCoD4oF4oG8oDaA1hCAFwDOwATnAHYDmAumVKlAL4BQXEAHmAD21YFDoBDALYQKYcQmgANPDyhqo-ISKihIUAIJpMOAgHIIk0wBooigHQAhI0ygB6V8gC0njdWrCoQTodAAs4CigAG3oIHi51DQFhUV1oJwxsWEQUAE07QwxMdy8fcToAE19-akDg4DCI6LpY7l4k7QlpWXloHJV49U1knXBoAuNCc0sbe3T0F2LvbziEoe1UqDnM+CRke3H0Lg4gA) – apokryfos Apr 10 '23 at 08:42
  • Yeah, it does work that way, but that's not an option unfortunately. The real generated code has multiple alternatives separated by pipes – Corno Apr 10 '23 at 21:20
  • It's a bit confusing with the X Y and Z since your first snippet seems to be referencing X and Y but Y is in the 2nd snippet. However if `B = Dict>` and `A = ['em', X.B]` then `A = [ 'em', Dict>` which I guess is fine like this but I am assuming if you make this into a union type it makes it impossible for TS to analyse it because at that point it will try to expand it which does indeed result in a circular resolution – apokryfos Apr 10 '23 at 23:30
  • Thank you about the feedback of the typo in the code snippet. I fixed it. For the rest of your remark; what changes in circular referencing when type parameters are added? – Corno Apr 11 '23 at 06:36
  • I don't fully understand it but there does seem to be quite a bit of "circular reference protection" (for lack of better term) built into TS but this snippet seems to trip it up. Look a [this example](https://www.typescriptlang.org/play?#code/C4TwDgpgBAIglgY2AHgCoD4oF4oG8oDaA1hCAFwDOwATnAHYDmAumVKlAL4BQXEAHmAD21YFFCQoAQTSYcAH0IByCAFtFAGigAhGUwDcPfkJFjw0HRmyxEKaRnQGoT5y4D0rgHoB+HrwHDRcWgAYRkrO0wFAmU1TR0I9CYoBXgkZATk7RlHF1z3by4gA). It only expands the type up to the point where it reaches itself. Somehow in your particular case this doesn't work. I'd try reporting this to the TS github – apokryfos Apr 11 '23 at 08:45
  • Your comment got me on a path to: https://github.com/microsoft/TypeScript/issues/41164. I realize what I can do to solve my issue. Thanks – Corno Apr 11 '23 at 13:14
  • Yes, the accepted answer is what I described in my own answer as well – Corno Apr 13 '23 at 08:24

1 Answers1

0

This link: https://github.com/microsoft/TypeScript/issues/41164 made me realise that in my case I can replace the 'Dict' type by a 'Dict' interface. Interfaces are more robust in these 'circular reference' cases.

Corno
  • 5,448
  • 4
  • 25
  • 41