Relative import from lib's secondary entry point Error TS5055: Cannot write file X.d.ts because it would overwrite input file
Krzysztof Platis
Posted on April 22, 2021
You might see the build error TS5055
due to various reasons. It can happen for instance when building an Angular library containing secondary entry points. Especially when the parent entry point imports items via a relative path from the secondary entry point's internal file. Instead, it should import items only via the secondary entry point's id.
❌ Bad:
import { X } from './child-entry-point/and/internal/file`;
✅ Good:
import { X } from '@namespace/parent-entry-point/child-entry-point’;
What does TS5055 error mean?
The TypeScript error TS5055
occurs when the build of a package outputs a file (i.e. xxx.d.ts
) which has existed and was already an input (a dependency) for building that package.
3 entry points and one faulty import path
Let's take an example, where such an error occurs. Say, our library has 1 primary entry point @lib/A
and 2 secondary entry points: @lib/A/B
, @lib/A/C
:
A/
├── a.ts
├── ng-package.json
├── B/
│ ├── b.ts
│ └── ng-package.json
└── C/
├── c.ts
└── ng-package.json
And here's the source code of Typescript files:
@lib/A
// a.ts
import { b } from '@lib/A/B';
import { c } from './C/c.ts'`; // BAD! path to internal file of @lib/A/C
@lib/A
depends on @lib/A/B
. But it DOES NOT depend on @lib/A/C
, because the file ./C/c.ts
is imported relatively, as the source code of the @lib/A
.
@lib/A/B
// b.ts
import { c } from '@lib/A/C';
export const b = 'b';
@lib/A/B
depends on @lib/A/C
.
@lib/A/C
// c.ts
export const c = 'c';
@lib/A/C
is independent.
Building the library and getting the error
Now let’s build our lib:
$ ng build --prod A
ng-packgr will build the entry points in the following order:
- ✔️ succesfull compilation of
@lib/A/C
producesdist/A/C/c.d.ts
- ✔️ succesfull compilation of
@lib/A/B
producesdist/A/B/b.d.ts
- ❌ compilation of
@lib/A
throws the error:TS5055: Cannot write file 'dist/A/C/c.d.ts' because it would overwrite input file
Why dist/A/C/c.d.ts
was both the input and output file for the build of @lib/A
?
- The input typings for building
@lib/A
are both:/dist/A/B/b.d.ts
and/dist/A/C/c.d.ts
. It's because@lib/A
depends on@lib/A/B
and indirectly also on@lib/A/C
(as@lib/A/B
depends on@lib/A/C
). - The source code of
@lib/A
references directly an internal file from the directory./C
. So the build produces not only/dist/A/a.d.ts
, but also attempts to produce/dist/A/C/c.d.ts
file. And this causes the error, because/dist/A/C/c.d.ts
has been already the input typing!
Real example
Here's a fix of the above error in the real world library (when running yarn build:libs
).
How to prevent a relative path import from a secondary entry point?
As of now, I don’t know.
Do you know any linter enforcing imports only from secondary entry point's id? I'm super happy to learn about it! In that case, please let me know in a comment or message me on twitter. Many thanks!
Posted on April 22, 2021
Join Our Newsletter. No Spam, Only the good stuff.
Sign up to receive the latest update from our blog.