microsoft / TypeScript

TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
https://www.typescriptlang.org
Apache License 2.0
101.22k stars 12.52k forks source link

TypeScript complains about overwriting .d.ts files that are potentially known outputs #16749

Open ORESoftware opened 7 years ago

ORESoftware commented 7 years ago

Using tsc at the command line, I got

error TS5055: Cannot write file '/Users/alexamil/WebstormProjects/oresoftware/ldap-pool/index.d.ts' because it would overwrite input file.

why? :)

my tsconfig.json file is as follows

{
  "compilerOptions": {
    "declaration": true,
    "baseUrl": ".",
    "types": [
      "node"
    ],
    "typeRoots": [
      "node_modules/@types"
    ],
    "target": "es5",
    "module": "commonjs",
    "noImplicitAny": true,
    "removeComments": true,
    "allowUnreachableCode": true,
    "lib": [
      "es2015",
      "es2016",
      "es2017"
    ]
  },
  "compileOnSave": false,
  "exclude": [
    "node_modules"
  ]
}
ORESoftware commented 7 years ago

nope, it's not because of the include property, I removed it, and same problem. this is a weird one folks.

DanielRosenwasser commented 7 years ago

If you remove the include field, then it implicitly includes everything. I guess you could consider excluding .d.ts files, but the point is that .d.ts is a valid input as well.

It would be helpful to get feedback from others on this.

the1mills commented 7 years ago

But generated .d.ts files are not input files!

As you can see in this case that it's being autogenerated.

Why would tsc complain?

DanielRosenwasser commented 7 years ago

.d.ts files could be generated, or could be written by hand to fill in for an input .js file. Keeping this in mind is important, especially as we consider supporting .d.ts emit from .js files going forward.

DanielRosenwasser commented 7 years ago

I still don't think the configuration is appropriate - .d.ts output files are being included in your input files which would be a problem for any project configuration I've ever seen.

the1mills commented 7 years ago

Daniel, sorry if I wasnt clear ( i am the same person as oresoftware). But two days ago on this thread I clearly stated that the same exact problem occurs when I remove the includes entry altogether from tsconfig.json. This issue does not have to do with the includes property.

kitsonk commented 7 years ago

As Daniel stated:

If you remove the include field, then it implicitly includes everything.

Outputting to the same path that your input from is a folly that will cause you endless heartache. How do you expect tsc to determine the difference between a generated .d.ts and one that was intentionally added as an input file? Definition files can be both input and output files.

ORESoftware commented 7 years ago

@kitsonk this is almost certainly operator error on my part - I have 10+ typescript projects and only this one is suffering from the problem, and I have such a simple configuration, I don't know what's going on yet.

But as far "How do you expect", the answer is simple..

I have an index.ts file + declaration:true therefore, tsc should be smart enough to know that index.d.ts would be a generated file. There is no way it wouldn't be autogenerated given my setup.

And therein lies my bemusement.

ORESoftware commented 7 years ago

I updated the original question - I have only one tsconfig.json file in the project and this is barebones and is causing the problem still.

error TS5055: Cannot write file '/Users/alexamil/WebstormProjects/oresoftware/ldap-pool/index.d.ts' because it would overwrite input file.

ORESoftware commented 7 years ago

here is a link to the project, if you want to see the problem for yourself:

https://github.com/ORESoftware/ldap-pool

ORESoftware commented 7 years ago

If I do this:

 "include":[
    "*.ts",
    "!*.d.ts"
  ]

then it does not complain - however, I swear I have other projects where I do not need to use that includes property, and they work fine, I am confused.

hoegge commented 7 years ago

What version of TSC do you use? When using TSC 1.8 I have the problem below but is gone with version 2.4:

If you generate output in same folder as input you can get the error

TS5055: cannot write file 'file.d.ts' because it would overwrite input file.

This is (off course) because tsc reads also the *.d.ts files. But when I add the option "exclude": [ "**/*.d.ts" ] " to tsconfig.json the error does not go away. That means that tsc does actually not exclude the files I've specified.

iamchathu commented 5 years ago

I also have this issue. I have turned "declaration": true and it complains about build folder already generated d.ts file when i run again tsc

the1mills commented 5 years ago

potentially solved by using the rootDir option:

{
  "compilerOptions": {
    "outDir": "dist",
    "rootDir": "src",
  },
  "include": [
    "src"
  ]
}
boneskull commented 5 years ago

I'm getting bit by this.

Both cases are valid. I would prefer an option to overwrite them, e.g. overwriteDeclarations.

Meanwhile, find src -name '*.d.ts' -exec rm {} \; && tsc 😝

boneskull commented 5 years ago

(my use case is generating .d.ts files from JavaScript, where those .d.ts files live alongside their .js counterparts; I'm using #32372)

RomainMuller commented 4 years ago

I am facing a similar issue with the following tsconfig.json:

{
  "compilerOptions": {
    "alwaysStrict": true,
    "charset": "utf-8",
    "composite": true,
    "declaration": true,
    "declarationMap": true,
    "incremental": true,
    "inlineSourceMap": true,
    "lib": ["ES2018"],
    "module": "CommonJS",
    "moduleResolution": "node",
    "resolveJsonModule": true,
    "strict": true
  },
  "include": [
    "**/*.ts",
    "**/package.json"
  ]
}

And then whenever I try to do import { version } from './package.json';, the second compilation attempt yields a TS5055 complaining about the package.d.ts that corresponds to package.json.

The reason I think this is incorrect behavior is because it differs to the behavior around .ts files: I can include any pattern of .ts files, and the .d.ts files that correspond to them will not be considered input files... but the .d.ts file corresponding to anything else will be. The difference in treatment is pretty annoying, especially as your typical CI/CD or PR validation build will run on a clean tree (and work), but in a local development environment, the second attempt to build will fail in a surprising way.

sirreal commented 4 years ago

I've also run into this issue which I documented here. Quoting:

I'm hitting an issue with is-shallow-equal and I believe it's because the build output is not in a different directory tree from the source files. I've tried a number configurations for tsconfig with no success.

If the generated types exist and the TypeScript build needs to regenerated them, for example source changes or missing .tsbuildinfo, the job will error with:

TS5055: Cannot write file '…/build-types/….d.ts' because it would overwrite input file.

It seems packages/is-shallow-equals/build-types/*.d.ts are being interpreted as source that cannot be overwritten. These are exactly the files we'd like to generate.

To reproduce this issue, do the following:

npm run clean:packages                                ## Clean everything (generated types and tsbuildinfo)
npm run build:package-types                           ## Generate declaration files
echo '// noop' >> packages/is-shallow-equal/index.js  ## Change file to trigger regeneration
npm run build:package-types                           ## !!! ERROR !!!

You'll see the following errors:

error TS5055: Cannot write file '…/gutenberg/packages/is-shallow-equal/build-types/arrays.d.ts' because it would overwrite input file.
error TS5055: Cannot write file '…/gutenberg/packages/is-shallow-equal/build-types/index.d.ts' because it would overwrite input file.
error TS5055: Cannot write file '…/gutenberg/packages/is-shallow-equal/build-types/objects.d.ts' because it would overwrite input file.

The same issue does not occur with other packages where the output directory is isolated from the source directors. For example, a11y does not have the same problem:

npm run clean:packages                        ## Clean everything (generated types and tsbuildinfo)
npm run build:package-types                   ## Generate declaration files
echo '// noop' >> packages/a11y/src/index.js  ## Change file to trigger regeneration
npm run build:package-types                   ## No problem

I've investigated (related issues linked below) and attempted many configuration combinations to get this to work as expected without success. I've gone as far as packages/is-shallow-equals/tsconfig.json as follows:

{
// We wouldn't use this configuration
// It demonstrates different suggestions that have been tried to fix the issue
  "compilerOptions": {
      "allowJs": true,
      "checkJs": true,
      "composite": true,
      "emitDeclarationOnly": true,
      "rootDir": ".",
      "outDir": "build-types",
      "declarationDir": "build-types"
  },
  "exclude": [ "build-types/**/*" ],
  "files": [ "arrays.js", "index.js", "objects.js" ],
  "include": [ "arrays.js", "index.js", "objects.js" ]
}

Apparently related issues:

leilapearson commented 4 years ago

I ran into this issue too. It seems like some part of the compilation process isn't recognizing that it is inside an excluded directory.

I don't don't see the problem if I do this:

  "exclude": ["**/*.d.ts", "dist", "node_modules"]

I do see the problem if I do this:

  "exclude": ["dist/**/*.d.ts", "dist", "node_modules"]

or this:

  "exclude": ["**/dist/**/*.d.ts", "dist", "node_modules"]

The error occurs despite the fact that the files it is complaining about are clearly inside dist:

error TS5055: Cannot write file '/Users/leila/dev/wip/jest-fp-ts/dist/index.d.ts' because it would overwrite input file.
error TS5055: Cannot write file '/Users/leila/dev/wip/jest-fp-ts/dist/matchers/index.d.ts' because it would overwrite input file.

In my case I have imports set up where src/index.ts imports and re-exports from src/matchers/index.ts which in turn imports and re-exports from src/matchers/eitherMatchers/index.ts.

The first two files are the ones causing the compilation errors. The third file is fine. So it looks like it might be related to how the import / export tree is affecting compilation.

Thought this might be a clue worth mentioning...

arcsector commented 4 years ago

At the very least there should be a flag that allows you to force an overwrite.

m-mohr commented 4 years ago
    "exclude": [
        "src/*.d.ts",
        "src/builder/*.d.ts"
    ],
    "include": [
        "src/*.js",
        "src/builder/*.js"
    ],

This also gives the error although I explicitly only include .js and exclude .d.ts. Still complains about input .d.ts overwrite...

hhanesand commented 3 years ago

Hello everyone. I was facing this error today and I found another possible cause for you.

Check if you are importing something like: import { SomeType } from '..'. I was using this in test/some_test.test.ts to import a type declared in ./index.ts. Nothing I changed in the include or exclude options helped.

My fix was to import from ../index instead.

You'll still need to to exclude dist, but I was getting this error regardless. For example :

"files": ["index.ts"],
"include": ["./**/*.ts"],
"exclude": ["node_modules", "dist"]

Can anyone else confirm?

ArturLuisOliveira commented 3 years ago

I faced the same issue, I've fixed it by ignoring test files and by removing logic from the index file, using it only for exports.

sheetalkamat commented 3 years ago

You can use --explainFiles to see why the file is in the program.

silkentrance commented 2 years ago

I am having the same issue with vitest + coverage with istanbul. It seems as if vitest is transpiling the code again and trying to replace existing files that have already been generated and are being used as input.

If i add

  "exclude": [
    "dist/*.d.ts"
  ],

to tsconfig.json everything will work just fine.

I am still wondering whether this will impact other workflows, e.g. packaging and publishing to npm...

ITenthusiasm commented 1 year ago

It would be helpful to get feedback from others on this.

@DanielRosenwasser From the perspective of someone using only JavaScript (via JSDocs in .js files and 1 or 2 .d.ts files when needed), being able to prevent [generated] .d.ts files from being included as inputs is very helpful.

For my use case, I'm working in a monorepo. TypeScript is able to type my entire monorepo with JSDocs. So I don't use the generated .d.ts files at all -- except for npm publishing. Because I'm working with JSDocs, I have a configuration like this:

{
  "compilerOptions": {
    "target": "ES2020",
    "module": "NodeNext",
    "moduleResolution": "NodeNext",
    "strict": true,
    "allowJs": true,
    "checkJs": true,
    "declaration": true,
    "emitDeclarationOnly": true,
    "forceConsistentCasingInFileNames": true
  },
  "include": ["./**/*.js"],
  "exclude": ["./index.js", "./**/*.d.ts"]
}

Ideally, for build + release, I would simply say, "Generate the output .d.ts files. Then publish everything in this workspace folder that isn't a test file." Unfortunately, this does not work. Despite my setup, TypeScript still complains about potentially overwriting .d.ts files that are strictly outputs. This is undesirable because of its impact on my build + release process.

During a build + release, it's more convenient for me to say, "Generate (or re-generate) the output .d.ts files. Then publish everything in this workspace folder that isn't a test file" than it is for me to say, "Delete all of the generated .d.ts files. Then re-generate the .d.ts files. Then publish everything in this workspace folder that isn't a test file" or for me to say "Generate the types in a separate build folder. Then copy all .js files to the build folder. Then copy package.json and ...".

In the end, I'm just going to write "prebuild: npm run remove-output-d-ts-files" and "build: tsc" as npm scripts for the build step. But if developers have to do this, it's a sign that they know what's an input and what's an output. To me, it would make sense if TypeScript was updated so that this extra inconvenient step wouldn't be necessary anymore.

ITenthusiasm commented 1 year ago

.d.ts output files are being included in your input files which would be a problem for any project configuration I've ever seen.

Agree that output .d.ts files definitely should not be included as inputs. I would just like to be able to specify what should be excluded by using tsconfig.json. boneskull hit the nail on the head with a small comment.

SalamandraDevs commented 1 year ago

I was facing this same error for two reasons:

  1. I putted a my-module.d.ts file with a module declaration (declare module 'my-module') inside the src/ folder trying to find a solution for another problem.
  2. I linked my-module types to node_modules/@types/my-module with a symlink.

Delete both solved the problem.