29

I'm developing a module A. The user can, optionally, inject a Winston logger to my module, therefore winston is its peer dependency.

Whenever I install my module A in another module where I don't want to log stuff (therefore I don't include Winston) and try to tsc it, Typescript yells:

Cannot find module 'winston' or its corresponding type declarations.

How do I go about it?

blackgreen
  • 34,072
  • 23
  • 111
  • 129
John Smith
  • 3,863
  • 3
  • 24
  • 42

2 Answers2

52

Since NPM v7.x, you can use the peerDependenciesMeta package.json config, which allows exactly that option.

For example, in your "Module A" package.json:

"peerDependencies": { 
  "winston": "> 1.0.0 <= 1.2.10",
  "foo": "~2.3.0"
},
"peerDependenciesMeta": {
  "winston": {
    "optional": true
  }
}

In this case, when installing Module A as a dependency of another project, it will allow installing winston dependency version in the semver range specified > 1.0.0 <= 1.2.10, but if it's not present at all, you won't get errors, so it will be allowed as well.

Note that following this example, foo dependency would be still required because it's not marked as optional.

Extra tip: you can check and test ranges on available NPM packages using this utility https://semver.npmjs.com/, it helped me as well.

PS. this is my first answer on SO! :)

Dharman
  • 30,962
  • 25
  • 85
  • 135
tmilar
  • 1,631
  • 15
  • 19
9

Just a small addition to @tmilar's answer. I'm using the same way to add optional dependancy (and also winston :)) the example is for npm@7 which supports peerDependenciesMeta

"peerDependencies": { 
  "winston": "~3.3.0"
},
"peerDependenciesMeta": {
  "winston": {
    "optional": true
  }
}

for optional dependencies you should expect exceptions on require and check package versions

let winston;
let winstonVersion;
try {
  winston = require('winston')
  winstonVersion = require('winston/package.json').version
} catch (er) {
  winston = null
}

if (isUnsupportedVersion(winstonVersion) ) {
  winston = null
}

// .. then later in your program ..

if (winston) {
  winston.doSomething()
}
Anatoli Klamer
  • 2,279
  • 2
  • 17
  • 22