Skip to content

Project references cause TS5055 #29549

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
haggholm opened this issue Jan 23, 2019 · 5 comments
Closed

Project references cause TS5055 #29549

haggholm opened this issue Jan 23, 2019 · 5 comments
Assignees
Labels
Needs More Info The issue still hasn't been fully clarified Scenario: Monorepos & Cross-Project References Relates to composite projects (a.k.a references between "medium sized projects")

Comments

@haggholm
Copy link

TypeScript Version: 3.2.4, 3.3.0-rc

Search Terms: TS5055, overwrite input file

Code

Unfortunately, I have thus far been unable to reproduce the exact issue in a minimal scenario; the following is code where I tried to reproduce it. I have only seen it (but frequently) in a more complicated, and proprietary, source tree. What I am thus far able to do is show that the output files show up where they shouldn’t.

The problem: When I have a parent project with child references, some of which children are interdependent, the output files of one package become input files for another package, and both are treated as input files by tsc, even though they are listed as output files in the package that owns them. For example,

test$ tree
.
├── build
│   └── packages
├── node_modules
│   └── @scope
│       ├── child1 -> ../../packages/child1
│       └── child2 -> ../../packages/child2
├── package.json
├── packages
│   ├── child1
│   │   ├── build
│   │   │   ├── index.d.ts
│   │   │   └── index.js
│   │   ├── package.json
│   │   ├── src
│   │   │   └── index.ts
│   │   └── tsconfig.json
│   └── child2
│       ├── build
│       │   ├── index.d.ts
│       │   ├── index.js
│       │   ├── something.d.ts
│       │   └── something.js
│       ├── package.json
│       ├── src
│       │   ├── index.ts
│       │   └── something.ts
│       └── tsconfig.json
├── tsconfig.json

(https://github.com/haggholm/ts5055)

Because child1 depends on child2 and vice versa, if you run tsc --listFiles from the parent directory, the output files are listed. Because they are treated as input files, tsc refuses to overwrite them.

Perhaps tsc --build should determine input/output files on a more strictly per-project basis?

Expected behavior:

Updating files in one package should obey the input/output rule of that package’s tsconfig. tsc --listFiles should not list anything under packages/*/build, since they’re excluded by the respective packages/*/tsconfig.json.

Actual behavior:

Output files of child1 are treated as input files because they are imported by child2. Output files show up in tsc --listFiles.

Related Issues: There are many TS5055-related issues, but I did not find any that are specifically related to project references/tsc --build.

@weswigham weswigham added Needs Investigation This issue needs a team member to investigate its status. Scenario: Monorepos & Cross-Project References Relates to composite projects (a.k.a references between "medium sized projects") labels Jan 23, 2019
@inversion
Copy link

I haven't got a minimal reproduction of my own - but I have noticed this seems to stop happening after a tsc --build --clean (obviously not ideal as it effectively disables incremental builds).

@RyanCavanaugh RyanCavanaugh added Needs More Info The issue still hasn't been fully clarified and removed Needs Investigation This issue needs a team member to investigate its status. labels Aug 22, 2019
@RyanCavanaugh
Copy link
Member

I'm not clear what the bug here is supposed to be - are you just missing exclude entries? The rules for which files tsc includes are pretty much set in stone; it's intentional that TS doesn't try to guess what other excludes should be present (what if you did want them included in the build?)

@stephenh
Copy link

FWIW I just hit this b/c a file accidentally added an import to the build directory, i.e.:

import { Foo } from "other-project/build/..."

Instead of:

import { Foo } from "other-project"

This got other-project's build directory pushed on to the input (i.e. it showed up in --listFiles) despite being excluded.

@desmap
Copy link

desmap commented Jul 15, 2020

I have the same problem and can't understand how this should work at all: references forces me to use declaration files and on every incremental run I get a TS5055 with ... because it would overwrite input file.

This whole thing (project references) is barely workable, doesn't make any sense or I missed something.

@isaacs
Copy link

isaacs commented Mar 23, 2023

This happened in a project I'm working on because I set up a monorepo. The comments were helpful here in unpacking it, so thank you all for that, but it was a head-scratcher for sure.

more details about the monorepo-specific situation, skip if you already grok the issue

I have a package in my workspace setup at ./packages/test that exports a Test class which extends a base class defined in ./packages/core.

The base class, for purposes of overly convoluted plugin reasons, does import type { Test } from '@tapjs/test'.

When they were separate packages that I was hand-crafting by means of npm pack and then installing the tarball, everything worked fine. But as linked workspaces, it all blew up, because the set of input files that @tapjs/test was using followed the symlinks into the actual source destination of the @tapjs/core package, which load the built artifacts that I was about to generate, and it did the same thing, so it found a cycle and concluded that I was overwriting an input file.

The solution that I'm using:

Put this in package.json for both packages:

{
  "scripts": {
    "prepare": "tsc -p tsconfig.json && tsc -p tsconfig-esm.json && bash ./scripts/fixup.sh",
  }
}

(The double-build isn't new, that's the hybrid-module setup, to build esm into one folder and cjs into another.)

Then, in both tsconfig files, I changed this:

{
  "outdir": "dist/esm" // or "dist/cjs"
}

to this:

{
  "outdir": "dist-tmp/esm" // or "dist-tmp.cjs"
}

And in fixup.sh, I added this:

#!/usr/bin/env bash
rm -rf dist    # remove the previous build
mv dist-tmp dist    # put the new build in place

Because the package.json fields "main", "module", and "exports" all refer to "./dist/..., it doesn't see the built artifacts as something it's about to destroy, because it thinks it's writing to ./dist-tmp.

Interestingly, this only happened when running npm install or prepare from the root of the workspace. When I ran npm run prepare in the package itself, it worked fine, presumably because of some difference in how it builds the files table.

@RyanCavanaugh RyanCavanaugh closed this as not planned Won't fix, can't repro, duplicate, stale Aug 6, 2024
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Needs More Info The issue still hasn't been fully clarified Scenario: Monorepos & Cross-Project References Relates to composite projects (a.k.a references between "medium sized projects")
Projects
None yet
Development

No branches or pull requests

7 participants