I am trying to reorganize the import/export statements of my TypeScript React project to make them shorter and cleaner, basically by the approach of defining an index.ts file in each feature specific folder to export resources (interface/type/function etc.) of that feature. This Smarter way to organize "imports" blog explains almost the same idea.
But suddenly jest execution breaks with below stack trace after the changes. The entities involved have been spoofed for confidentiality purpose.
Test suite failed to run
TypeError: Cannot read property 'FooBarEnum' of undefined
at Object.FooBarEnum (src/features/Zoo/index.ts:93:23)
at Object.<anonymous> (src/features/CarPark/CarParkManager.ts:18:4)
at Object.<anonymous> (src/features/CarPark/index.ts:1:1)
at Object.<anonymous> (src/features/Zoo/ZooManager.ts:1:1)
at Object.<anonymous> (src/features/Zoo/index.ts:14:1)
at Object.<anonymous> (src/features/Rabbit/Rabbit.ts:4:1)
at Object.<anonymous> (test/features/Rabbit/Rabbit.test.ts:2:1)
Basically there is an enum defined in a constant file which can't be read at all.
I am pretty sure my jest setup is correct because it was executing successfully before this. And I use babel-jest and @babel/preset-typescript to compile.
Appreciate if someone can point me to a path for debugging as the stack trace doesn't really tell much.
Finally I realized this is caused by a hidden circular dependency in my code base.
[TL;DR] Dependency cycle:
Rabbit>Zooindex >CarParkindex >Zooindex.[Details] The situation is that
ZooManageris exported from the index file ofZoofolder, andZooManagerimportsCarParkManagerwhich is exported from the index file ofCarParkfolder. 'FooBarEnum' is exported from the index file ofZoofolder and is used byCarParkManager, and that constitutes the dependency cycle.I know the given spoofed example isn't really nice to read upon but this provides a hint that when you encounter similar issues, keep an eye on circular dependencies.
The import/no-cycle ESLint rule can be added to carry out a static check.
And the madge developer tool can be used to construct a visual module dependency graph.
References: