I'm trying to build a private module that I know will only be used by another TypeScript project.
According to this (https://github.com/Microsoft/TypeScript/issues/5225) I should be able to simply import my other project without needing to build type definitions.
The problem is I'm missing the type definitions for any dependencies on that library when I try to import it.
Here's the situation:
Lets say you have two projects. lib
and app
. app
imports lib
, a pure TypeScript node module.
├── app/ │ ├── dist/ │ │ ├── index.d.ts │ │ ├── index.js │ │ └── index.js.map │ ├── src/ │ │ └── index.ts │ ├── package.json │ ├── package-lock.json │ └── tsconfig.json └── lib/ ├── src/ │ └── index.ts ├── package.json ├── package-lock.json └── tsconfig.json
app
simply imports a function from lib
and runs it:
import lib from "lib";
lib("test");
Lib imports a dependency and its types, and exports a function:
package.json
:
"dependencies": {
"dotenv": "^6.1.0"
},
"devDependencies": {
"@types/dotenv": "^4.0.3",
"typescript": "^3.1.6"
}
app/src/index.ts
:
import dotenv from "dotenv";
dotenv.load()
export default (message: string) => {
console.log(message);
}
When I try to build app
I get an error about the missing type definitions from the the lib
dependency:
node_modules/lib/src/index.ts:1:20 - error TS7016: Could not find a declaration file for module 'dotenv'. 'lib/node_modules/dotenv/lib/main.js' implicitly has an 'any' type. Try `npm install @types/dotenv` if it exists or add a new declaration (.d.ts) file containing `declare module 'dotenv';` 1 import dotenv from "dotenv";
What's the proper way to handle this scenario? It'll work fine in a mixed JS / TS module, because the "compile boundary" will end at the imported module and its exposed types, but since this module is "pure" TypeScript, it'll crawl all of its dependencies as if it were one large repo.
What's the proper way to set this up? Or is the real issue that npm install
doesn't install the dev dependencies? Should I install all of the @types
as prod dependencies?
There are two possible module resolution strategies: Node and Classic. You can use the moduleResolution option to specify the module resolution strategy. If not specified, the default is Node for --module commonjs , and Classic otherwise (including when module is set to amd , system , umd , es2015 , esnext , etc.).
To get the JavaScript files for the TypeScript modules, we need to compile modules using TypeScript compiler. Compilation of a module depends on the target environment you are aiming for. The TypeScript compiler generates the JavaScript code based on the module target option specified during compilation.
ts-node is a TypeScript execution engine and REPL for Node. js. It JIT transforms TypeScript into JavaScript, enabling you to directly execute TypeScript on Node. js without precompiling.
According to this: https://www.typescriptlang.org/docs/handbook/declaration-files/publishing.html
The recommendation is to install all dependencies, as prod dependencies:
Our package exposes declarations from each of those, so any user of our browserify-typescript-extension package needs to have these dependencies as well. For that reason, we used "dependencies" and not "devDependencies", because otherwise our consumers would have needed to manually install those packages. If we had just written a command line application and not expected our package to be used as a library, we might have used devDependencies.
So basically if you are writing a typescript npm module, all dependencies must be prod dependencies.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With