Typescript: Import type from package without dependencies from other types in the same package
Asked Answered
S

1

9

I have a NPM package written in Typescript (let's call it libd) that offers some classes and types. They are exported in a index.ts file like this:

export { ClassA } from "./ClassA";
export { TypeB } from "./TypeB";

The ClassA is using an external dependency (let's call it depc) that is set to peerDependencies in the package.json. The TypeB is just a type without any external dependencies.

In the package.json the main field is set to dist/index.js (where it is transpiled to) and types are set to dist/index.d.ts.

The tsconfig.json of the libd package looks like this:

{
  "compilerOptions": {
    "target": "ES2019", 
    "module": "commonjs",
    "declaration": true,
    "outDir": "dist",
    "rootDir": "src",
    "inlineSources": true,
    "inlineSourceMap": true
  }
}

Now I im consume the TypeB in another library (let's call it libe) without importing ClassA and without having the depc dependency installed. The libd library is installed via NPM and the type is imported like this:

import { TypeB } from "libd";

The tsconfig.json of libe is similar to the one from libd.

Transpiling this gives me the error TS2307: Cannot find module 'depc'.

Now I understand, if I would use ClassA I must install depc since it imports it. But I'm only using TypeB that does not require any dependencies and sometimes types come with the original package.

I could fix this problem by installing @types/depc and Typescript would be happy. Code should work at runtime, since no actual usage of depc comes from libe. But I would rather not install useless packages.

Setting "skipLibCheck": true in the tsconfig.json of libe would also fix the tsc error but I am not sure what negative impacts this would have.

So my question is: Why does typescript check a class from dependency that I am not importing? Is it, because I have bundled all exports of the libd package in an index.ts file and all imports of those are going through this index file?

Can I resolve this without separating TypeB and ClassA into different packages? That would make them very small packages and for ~80% of the time they would be installed both.

Seavir answered 22/4, 2020 at 11:14 Comment(0)
S
2

Is it, because I have bundled all exports of the libd package in an index.ts file […]?

Yes.

TypeScript compiler sees that you are using the file libd/dist/index.{js|d.ts} and starts evaluating its exports. While doing so, it finds out that ClassA is using depc, and goes for evaluating depc, – but it is nowhere to be found (since it isn't installed). That's a definitive error.

TypeScript compiler doesn't check whether you are using ClassA or not, it is not its job to perform tree shaking.

Using "skipLibCheck": true is actually a good way of solving this problem, since its description states explicitly:

Rather than doing a full check of all d.ts files, TypeScript will type check the code you specifically refer to in your app’s source code.

… which is ultimately what you want, right?

Sedition answered 21/11, 2021 at 18:23 Comment(1)
Yes we have moved to set it in our tsconfig.json by now. thank you anyway for the explanation.Seavir

© 2022 - 2024 — McMap. All rights reserved.