The import of my library using package.json exports is failing due to TypeScript compilation errors

I am currently developing a JavaScript library that I want to make importable via script tags, ES6 imports, and traditional Node requires, with or without TypeScript or any build systems. However, I am facing challenges in achieving this.

Within my package.json file, I have specified the following exports (simplified for clarity):

"exports": {
    ".": {
        "require": "./dist/slim.copper.cjs",
        "import": "./dist/slim.copper.js",
        "types": "./dist/typed.copper.d.ts"
    },
}

In a test TypeScript project, I import my library using the statement:

import Copper from "@jwrunge/copper";

While type hints and intellisense work well, and I can compile the code to JavaScript successfully, I encounter an error when running the JS code with Node:

C:\Users\jrunge\Documents\CODE\copper_test\src\index.js:3
var copper_1 = require("@jwrunge/copper");
               ^

The require statement for slim.copper.js within C:\Users\jrunge\Documents\CODE\copper_test\src\index.js needs to be changed to a dynamic import() as it is supported in all CommonJS modules.
    at Object.<anonymous> (C:\Users\jrunge\Documents\CODE\copper_test\src\index.js:3:16) {
  code: 'ERR_REQUIRE_ESM'
}

Although the JavaScript output from TypeScript retains the appropriate typing, it uses require as shown below:

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
var copper_1 = require("@jwrunge/copper");
var store1 = copper_1.default.store("foo", { value: 12 });

Interestingly, when I console.log copper_1 in the JS output and comment out all other code, the result is:

{
  store: [Function: store],
  ustore: [Function: ustore],
  getFunc: [Function: getFunc],
  addFuncs: [Function: addFuncs],
  config: [Function: config]
}

It seems that the imported copper_1 does not have a default property and is a direct import of the .cjs file, which aligns with the usage of require.

  1. Could it be that the JS output is utilizing the .cjs version of the library, which does not have an export property like the .js version?
  2. What would be a recommended solution to address this issue while still supporting require imports? I am open to simple instructions for my users, but I prefer a solution that allows for better compatibility with various use cases.

If I refrain from supporting require and only provide es (.js) module files, the following error occurs (when trying to require an ES module):

Error [ERR_REQUIRE_ESM]: require() of ES Module C:\Users\jrunge\Documents\CODE\pubsub\dist\slim.copper.js from C:\Users\jrunge\Documents\CODE\copper_test\src\index.js not supported.
Instead change the require of slim.copper.js in C:\Users\jrunge\Documents\CODE\copper_test\src\index.js to a dynamic import() which is available in all CommonJS modules.
    at Object.<anonymous> (C:\Users\jrunge\Documents\CODE\copper_test\src\index.js:3:16) {
  code: 'ERR_REQUIRE_ESM'
}

Answer №1

Here is a potential solution, but I'm not fully satisfied with it as it feels more like a temporary fix.

When dealing with TypeScript, the import statement is compiled as require but still expects to access the default property. To workaround this, one can avoid using export default in the library source code. For example, instead of export default myExport, you can use export const Copper = myExport. Subsequently, the import statement changes from

import Copper from @jwrunge/copper
to
import {Copper} from @jwrunge/copper
.

By implementing this approach, both the .js file and the .cjs file in the importing project can be referenced interchangeably.

I am still eager to hear any alternative suggestions for dealing with the issue of export default in this scenario.

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

Tips for monitoring/faking method invocations within an Angular 5 service's constructor

My service involves making 2 method calls in the constructor: constructor(private http: HttpClient) { this.apiURL = environment.apiURL; this.method(); this.method2().subscribe(); } I am facing difficulties testing this service in the Test ...

Prevent Angular 4 Component Reloading

I need my component to remain stable without reloading every time a new page is accessed. Currently, it reloads on each page change which disrupts the functionality. This issue is particularly evident in the Header section where there is a Marquee that rel ...

"A collection of elements in Typescript that is uniform in type, denoted by

Is it possible to declare an array of type any[] where all elements are of the same type? For example: // Allowed const array1: any[] = [1, 2, 3]; const array2: any[] = ['a', 'b', 'c']; // Not allowed because it contains bot ...

Issues with navigation in React Native Typescript

Currently, I am in the process of developing a new React Native Expo project utilizing TypeScript. I have been attempting to configure navigation following the guidance provided in React Native's TypeScript documentation. However, upon running and sim ...

How can typescript configurations be imported/exported in a node environment?

I'm encountering difficulties while trying to set up a TypeScript node project and import modules: Below is the structure of my project: /build /src main.ts ...

Angular CLI - exploring the depths of parent-child component communication

My issue revolves around accessing the 'edit' method of a child component using @ViewChild, but for some reason it's not functioning as expected. Where could I possibly be going wrong? Here are the console logs: https://i.sstatic.net/wvpVN ...

What could be causing the availability of a response in a service, but showing as undefined in the component?

Currently, I am facing a problem with my service and component setup. While the service can successfully read the response as a JSON object, the component is returning res: undefined. service: constructor( private http: Http, private fbuilder: Fo ...

Executing a function for every element within a loop in Angular 11 - the Angular way

I'm currently developing a project using Angular in which users have the ability to upload multiple questions simultaneously. After adding the questions, they are displayed in a separate modal where users can include diagrams or figures for each quest ...

What is the best way to implement debouncing for an editor value that is controlled by the parent component?

Custom Editor Component import Editor from '@monaco-editor/react'; import { useDebounce } from './useDebounce'; import { useEffect, useState } from 'react'; type Props = { code: string; onChange: (code: string) => void ...

Unexpected token @ while using Angular2 with jspm and gulp for typescript compilation

Recently, I've delved into learning about Angular 2 and its accompanying technologies. In an attempt to create minified and "compiled" versions of my .ts files, I started using gulp-jspm-build. However, I encountered an error that has left me stumped. ...

What is causing ESLint to point out the issue with the @inheritdoc tag?

My code in ESLint is throwing an error about a missing JSDoc return declaration, even though I have included an @inheritdoc tag there: https://i.sstatic.net/QGxQh.png Here is the section from the interface I am inheriting from: export interface L2BlockSo ...

Leveraging GetServerSideProps for Dynamic URL Query Parameters

While working on querying the parameter in the URL within getServerSideProps, I encountered an error where ID was undefined in the DetailThemepage function. My Next.js version is V.13 and the directory structure is app/detail/[id]/page.tsx. http://loca ...

Encountering a 404 error with Angular 6 routing after refreshing the page when using an Nginx proxy

I currently have my angular application running within a docker container, exposed on port 83. Additionally, I have a separate spring-boot rest app running inside another docker container, exposed on port 8083. On the host server, there is an Nginx server ...

Limitations require a member to only accept a type (and not an instance) that extends or implements another type [TypeScript]

I'm seeking assistance with a set of abstract concepts in TypeScript. I am looking to restrict a member to only accept types as values, but those types must also implement or extend other types or interfaces. For example: The code snippet below is ...

Angular 5 Dilemma: Exporting UI Components without Locating Template

My current project involves developing UI Components that will be used in various web projects within the company. Our plan is to publish these UI components as an npm package on our local repository, and so far, the publishing process has been successful. ...

Testing the GET method in an Angular service: A guide

I'm currently facing an issue with my service method and unit test setup. Despite writing a unit test for the getter method, the coverage report indicates that this method is not covered. I would appreciate any advice on what might be going wrong in m ...

Can someone explain the meaning of this syntax in a TypeScript interface?

Just the other day, I was trying to incorporate the observer pattern into my Angular 4 application and came across this TypeScript code snippet. Unfortunately, I'm not quite sure what it means. Here's the code: module Patterns.Interfaces { ...

Tips for triggering an event from a function instead of the window

Everything is functioning as expected, with the event listener successfully capturing the custom event when it is dispatched from the window and listened for as loading, all seems to be working well. const MyLib = mylib(); function mylib() { const re ...

OpenAPI implementation in NestJS that emphasizes the use of reusable parameters

Is it possible to reuse common parameters in the implementation of NestJS OpenAPI/Swagger? This feature would prevent me from having to clutter my endpoint with repetitive @ApiImplicitQuery decorators. ...

Refresh Information Stripe

I'm currently working on implementing Stripe, and utilizing metadata in the process. Everything works smoothly until I come across a scenario where I need to update a value in the metadata to determine if a specific uuid has been used before. pay ...