Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What's the proper way to setup a "pure" typescript module

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?

like image 583
Gaidin Avatar asked Nov 05 '18 17:11

Gaidin


People also ask

What is default module resolution strategy in TypeScript?

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.).

How do I compile a module in TypeScript?

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.

How does ts-node work?

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.


1 Answers

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.

like image 119
Gaidin Avatar answered Nov 09 '22 06:11

Gaidin