First, make sure Node.js and Yarn are installed.
Then, run ./build-all.sh
.
In both expected
and actual
projects:
- The compilation
target
is set toes2015
and nolib
s are specified. According to the TypeScript docs, it means the following libraries are loaded by default:DOM
,ES6
,DOM.Iterable
,ScriptHost
. - The code in
index.js
usesObject.values
(which is a ES2017 feature) andBigInt
(which is a ES2020 feature).
The only difference between the 2 projects is that actual
has a (direct) dependency on @types/node
.
When building the expected
project, we get the following 2 errors:
$ tsc
index.ts:2:20 - error TS2339: Property 'values' does not exist on type 'ObjectConstructor'.
2 console.log(Object.values({ foo: BigInt(42) }));
~~~~~~
index.ts:2:34 - error TS2304: Cannot find name 'BigInt'.
2 console.log(Object.values({ foo: BigInt(42) }));
~~~~~~
Found 2 errors.
This is expected because neither the es2017
, es2020
, esnext
, etc. lib
s are included in the compilation.
However, when building the actual
project, none of these errors pop up:
$ tsc
✨ Done in 1.89s.
This is because the @types/node
dependency contains 2 files (this one and that one) that reference es2018
and esnext.bigint
, which in turn references es2017
.
Those libs then get implicitly added to the compilation.
Note that running tsc
and tsc --build
produces the same thing here.
Imagine you am building a project for the browser, with an explicit target of es2015
. By not including extra libraries, you rely on the type checker to barf if you use features not supported in ES2015.
However, one of your dependencies might be referencing to any lib
using a triple-slash directives and therefore break browser compatibility without the type checker informing you.
Of course, in this repository, one might just remove the dependency to @types/node
. But in practice, this is widely used, probably by one of your dependencies without you even knowing it.
For example, the @sindresorhus/is
package is making such reference, and this package is used a lot.
In our cases, we use apollo-cache-inmemory
, enzyme
(and @types/enzyme
), and got
, all of which have a dependency on @types/node
. Using the yarn why
on one of our projects, I get the following nested dependencies:
@types/enzyme > @types/cheerio > @types/node
apollo-cache-inmemory > optimism > @wry/context > @types/node
enzyme > cheerio > parse5 > @types/node
got > @types/cacheable-request > @types/node
got > @types/cacheable-request > @types/keyv > @types/node
got > @types/cacheable-request > @types/responselike > @types/node
To see this in action, the apollo-cache-inmemory
branch demonstrates the issue as well.
I am opening this reproduction repository because I am not sure how to solve this issue at the moment. I will update this repository with related links as I find out solutions.
In the meantime, I will be using eslint-plugin-es
to report features that should not be used and that the TypeScript checker did not error on.
$ node --version
v12.14.0
$ yarn --version
1.22.4