Creating and utilizing multi-module NPM packages written in Typescript: A comprehensive guide

For a while now, I've been quite at ease creating and utilizing NPM packages with Typescript. However, these packages have typically been provided and consumed as a single module. Now, I'm interested in publishing packages that contain more than one module without requiring the consumer to import unnecessary parts of the package into their code.

Let's say I have two typescript modules in my package src folder: one.ts and two.ts:

one.ts:

export function talk() { console.log("Hello World"); };

two.ts:

export function talk() { console.log("Goodbye World"); };

In accordance with best practices for creating an NPM package in Typescript, I also create an index.ts file in the src folder:

index.ts:

import * as one from "./one";
import * as two from "./two";
export { one, two };

This setup generates index.js, index.d.ts, one.js, one.d.ts, two.js, and two.d.ts files in the dist folder of my package (as well as possibly some source mapping files not relevant to this query).

The somewhat condensed package.json looks like this:

{
  "name": "my-package",
  "version": "0.0.5",
  "description": "",
  "license": "UNLICENSED",
  "main": "dist/",
  "types": "dist/",
  "scripts": {
    "build": "tsc --skipLibCheck",
    "prepublish": "yarn run build",
  },
  "keywords": [],
  "dependencies": {},
  "files": [
    "src",
    "dist"
  ]
}

Similarly, the truncated tsconfig.json is as follows:

{
  "compilerOptions": {
    "target": "es6",
    "module": "es6",
    "moduleResolution": "node",
    "noImplicitAny": true,
    "noEmitOnError": true,
    "removeComments": false,
    "declaration": true,
    "outDir": "./dist",
    "allowJs": false,
    "sourceMap": true,
    "typeRoots": [
      "./node_modules/@types"
    ]
  },
  "include": [ "src/**/*" ],
  "exclude": [ "node_modules" ],
  "compileOnSave": false
}

After publishing the package and consuming it in typescript, suppose I want to import only the one.ts module. I never need the "goodbye" part in my consuming code. How can I achieve this without unnecessarily importing the other module?

I'd like to be able to do something like this:

import * as greeting from "my-package.one"; 
greeting.talk();

Or even better:

import { talk } from "my-package.one"; 
talk();

I've managed to accomplish this before by writing javascript and creating my own header files with ambient modules. But this time, I want to keep things simple and use modules as they are intended in the package installed in node-modules.

If you have any suggestions on how I can modify my approach to building the multi-module package or how I consume it, I would greatly appreciate your input. Thank you!

Answer №1

Here is a suggestion:

import { speak } from "my-collection/dist/primary"

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Example of Node-gallery used in isolation, displaying an error event with the message "ENOENT"

I am currently experiencing an issue with the node-gallery npm module. After installing dependencies inside the /example directory, I attempted to run the app. The result was a localhost:3000/gallery page, but upon the page fully loading, I encountered the ...

Can Nexus be utilized to act as a proxy for a private npmjs organization?

Having a private npmjs.com org presents challenges in certain build environments where connections are limited, but fortunately I am able to connect to a Nexus repository. I have been trying to figure out if it's possible to create an NPM proxy with ...

Downgrade to previous version of socket.IO by rolling back the installation

Currently, I have socket.IO version 0.9.16 installed and I am looking to revert back to version 0.9.0. Can I downgrade by simply running npm install <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="681b070b030d1c4601072858465146 ...

What are the best techniques for streamlining nested objects with Zod.js?

As a newcomer to zod.js, I have found that the DataSchema function is extremely helpful in verifying API data types and simplifying the API response easily. However, I'm curious if there is a way to streamline the data transformation process for myEx ...

Do using an IIFE (Immediately-Invoked Function Expression) and using curly braces provide different outcomes?

(function() { let number = 10; console.log(number); // 10 })() // executed right away console.log(number); // this will throw an error: number is not defined VS { let number = 10; console.log(number); //10 } // immediately invoked console.lo ...

When selecting the "Open Link in New Tab" option in Chrome, the Angular app's routing will automatically redirect to the login page

I am facing a peculiar issue in my Angular 2 application that I need help troubleshooting. Currently, the routing within my app functions as intended when I click on links to navigate between different components. Here is an example of how the routing path ...

What is the best way to eliminate duplicate data from an HTTP response before presenting it on the client side?

Seeking assistance on how to filter out duplicate data. Currently receiving the following response: {username:'patrick',userid:'3636363',position:'employee'} {username:'patrick',userid:'3636363',position:&a ...

When I define a type in TypeScript, it displays "any" instead

Imagine a scenario where we have a basic abstract class that represents a piece in a board game such as chess or checkers. export abstract class Piece<Tags, Move, Position = Vector2> { public constructor(public position: Position, public tags = nul ...

Ember-cli opting for local version instead of global

This isn't just an EmberJS question, it might involve more npm/node related issues. After running npm install -g ember-cli, the version shown when checking with ember --version is: ember-cli: 3.10.1 node: 18.18.2 os: darwin x64 However, this is not ...

TurboRepo initiates the web server and promptly closes down without any issues

I have a turbo-repo set up using pnpm, and I am attempting to launch the React frontend for one of my clients with the following command: npx turbo run start --filter=testclient When executing this command, the output is as follows: • Packages in scope: ...

Tips for integrating jwt token into axios request

I am facing an issue with my backend endpoint. I can successfully retrieve a list of customers using jwt token on Postman, but when I try to fetch the list from a React app using axios get request, it fails. After reading through this question, I implemen ...

Is it possible to determine if NPM install is functioning correctly in various situations or does it vary?

npm init is the first step to start a project I have specified axios: "~1.2.4" in my package.json file When I execute npm install, it installs version 1.2.6, updating to the latest patch as expected If I use ^1.2.4 in package.json and run npm in ...

disappearing of vue event on single file component HTML element

I'm currently working on an ElectronJs project with Electron Forge, using the Webpack + Typescript template project In addition to that, I've integrated Vue and vue-loader for webpack in order to utilize Single File Component (SFC) files: { ...

Issue encountered with the sharp package during the installation of npm packages, resulting in the deletion of the node modules directory

Recently, I set up a new computer and decided to run Ubuntu 22.04 on it. After that, I installed node version 18.18. Currently, I am facing an issue while trying to install packages for a project that includes Sharp. The error message I am encountering is ...

Obtaining data from a TypeScript decorator

export class UploadGreetingController { constructor( private greetingFacade: GreetingFacade, ) {} @UseInterceptors(FileInterceptor('file', { storage: diskStorage({ destination: (req: any, file, cb) => { if (process.env ...

A step-by-step guide to customizing the Material UI Chips delete SVG icon to appear in white color through

Using a Material UI component, I added a custom class to my chip. Attached is a screenshot showing what I mean. Currently, I am attempting to change the color of the cross button to white. After inspecting the element, I discovered that it is an SVG ico ...

Enhancing Mocha and Chai tests: Exploring ways to increase strictness

While working with Mocha and Chai, I have come across numerous unreliable tests. I want all of these tests to fail. Similar issues on StackOverflow are often due to async problems and not using done(). Regardless, even if that were my problem, I would stil ...

What is the reason for TypeScript not displaying a type mismatch error in this particular instance?

After starting to use React with TypeScript, I defined my types as follows: type CardInfo = { cardIndex: null | number; title: string; note: string; _id: string; from: string; cardId: string; }; type ContentType = { title: string; note: st ...

Issues arise with React during the installation of styled-components

Every time I install other packages, it goes smoothly. However, when I try to install styled-components, I encounter the following error: npm ERR! Cannot read properties of null (reading 'edgesOut') npm ERR! A complete log of this run can be fo ...

Slice an interactive div

I am currently working on setting up a horizontal sliding div for a menu. The layout consists of a left DIV that remains visible at all times, and a sliding DIV that appears horizontally when the menu is activated. My HTML code looks like this. <div id ...