Description
I'm not even going to try to figure out a minimal repro, but I'm observing it happening in a real-world project while testing #935. Basically, this
Line 100 in d677d73
is supposed to return only the root file names, i.e., what TypeScript sees as “entrypoints,” i.e., excluding libs and imported modules that aren’t covered by include
or files
in the tsconfig.
However, what it’s doing here is returning all the script files Webpack knows about, in no particular order. This is a problem because later on, TypeScript will try to merge this array of files with more files, and the resulting order is important. However, since this array already contains all the other things TypeScript is trying to merge in, it’s a no-op and that important ordering never happens.
The particular symptom I’m observing is that, with transpileOnly: false
, my project compiles cleanly in the initial run, but when I modify a file that assumes the return value of setTimeout
is a number (which it is in the browser), I get errors because the type checker thinks setTimeout
is coming from @types/node
(which returns an object).
What’s happening under the hood is that on the first run, ts-loader isn’t yet aware of any lib files, so getScriptFileNames()
works, and TypeScript sorts lib files and typings files appropriately, such that the symbol for setTimeout
has a valueDeclaration
coming from lib.dom.d.ts, and some other declarations from @types/node
. But on the second run, ts-loader’s instance.files
contains lib files and typings for Node, and the ones for Node happen to come first, so that becomes the valueDeclaration
for the global symbol setTimeout
.
I actually think #348 might have been caused by this.
At any rate, I’m going to fix it. Just wanted to document it.