-
-
Notifications
You must be signed in to change notification settings - Fork 434
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
| [...files.keys()].filter(filePath => filePath.match(scriptRegex)), |
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.