The index.d.ts file for Bootstrap4 is unable to locate the 'popper.js' module when using TypeScript 3.9 and Libman in Visual Studio 2019

I currently utilize VisualStudio 2019 combined with TypeScript3.9 and Libman.

My requirement is for Bootstrap4 and jQuery libraries to be incorporated.

To achieve this, I attempt to obtain these libraries and typings(index.d.ts) via Libman.

However, upon obtaining the Bootstrap4 typing(index.d.ts), an error occurs stating "Cannot find module popper.js".

// Type definitions for Bootstrap 4.5
// Project: https://github.com/twbs/bootstrap/, https://getbootstrap.com
// Definitions by: denisname <https://github.com/denisname>
//                 Piotr Błażejewicz <https://github.com/peterblazejewicz>
// Definitions: https://github.com/DefinitelyTyped/DefinitelyTyped
// TypeScript Version: 2.3

/// <reference types="jquery"/>

import * as Popper from "popper.js";     // ERROR!: "Cannot find module popper.js"

Given similar queries raised in various communities:

  • Bootstrap 4 TypeScript Type Definition fails to compile - Cannot find module 'popper.js'
  • Cannot find module "popper.js" Angular 5 Visual Studio 2017 asp.net core
  • Angular @types/bootstrap error: Namespace 'popper.js' has no exported member

A mere temporary fix was identified.

In my case, altering the bootstrap4 typing(index.d.ts) to a relative path such as

import * as Popper from "../popper_v1";
proved effective in resolving the issue. Sadly, Libman overrides any manual adjustments made to the index.d.ts file.

_

The puzzle remains: How can I rectify this error?

Perhaps opting to install manually modified index.d.ts with Popper v1.X could offer a solution?

Your insights are greatly appreciated.


Steps to Reproduce the Error:

  1. Initiate ASP.Net4 MVC Project on .Net Framework 4.8

  2. Formulate libman.json to include desired libraries and TS typings

{
  "version": "1.0",
  "defaultProvider": "jsDelivr",
  "libraries": [
    {
      "library": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="7b1914140f080f091a0b3b4f554e5549">[email protected]</a>",
      "destination": "lib/bootstrap/"
    },
    {
      "library": "@types/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="caa8a5a5beb9beb8abba8afee4ffe4fa">[email protected]</a>",
      "destination": "lib/types/bootstrap/"
    },
    {
      "library": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="90fae1e5f5e2e9d0a3bea5bea1">[email protected]</a>",
      "destination": "lib/jquery/",
      "files": [
        "dist/jquery.js",
        "dist/jquery.min.js",
        "dist/jquery.min.map",
        "dist/jquery.slim.js",
        "dist/jquery.slim.min.js",
        "dist/jquery.slim.min.map",
        "external/sizzle/LICENSE.txt",
        "external/sizzle/dist/sizzle.js",
        "external/sizzle/dist/sizzle.min.js",
        "external/sizzle/dist/sizzle.min.map",
        "AUTHORS.txt",
        "LICENSE.txt",
        "README.md"
      ]
    },
    {
      "library": "@types/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="315b404454434871021f041f00">[email protected]</a>",
      "destination": "lib/types/jquery/"
    },
    {
      "library": "@types/<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="b0c3d9cacadcd5f0829e839e82">[email protected]</a>",
      "destination": "lib/types/sizzle/"
    },
    {
      "provider": "cdnjs",
      "library": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="e3938c93938691cd8990a3d2cdd2d5cdd2">[email protected]</a>",
      "destination": "lib/popper.js/"
    },
    {
      "provider": "filesystem",
      "library": "lib_ManualInstallSources/popper_v1/",
      "destination": "lib/types/popper_v1/"
    }
  ]
}

** Note: The typing(index.d.ts) of popper.js ver.1.X was sourced from the GitHub repository.

  1. Create tsconfig.json
{
  "compilerOptions": {
    "noImplicitAny": false,
    "noEmitOnError": true,
    "removeComments": false,
    "sourceMap": true,
    "target": "es5",
    "lib": [ "ES6", "DOM" ],
    "baseUrl": ".",
    "typeRoots": [
      "./lib/types"
    ]
  },
  "exclude": [
    "node_modules",
    "wwwroot",
    "lib"
  ]
}

Subsequent to performing these steps, the Bootstrap4 typing(index.d.ts) triggers an error stating "Cannot find module popper.js" when using

import * as Popper from "popper.js";
.


Answer №1

I came across two patterns that need fixing.

  1. Adjust the settings in tsconfig.json so the compiler can search the "lib" directory.
  2. Rename the directory of libraries through Libman to "node_modules" (Not recommended).

This issue stems from various reasons.

  1. TypeScript's default module management mechanism is rooted in node.js.
  2. Libman utilizes the "lib" directory as the default location for libraries.
  3. The names of directories containing libraries must match the ModuleName.

[Reasons]

1. TypeScript's module management is based on node.js.

My tsconfig.json has

"target": "ES5"
without the "module" property.

This defaults the "module" property to CommonJS under the "ES5" target.

Also, without the "moduleResolution" property, setting

"module": "CommonJS"
results in
"moduleResolution": "Node"
.

Thus, the compiler uses the Node module resolution system.

.

> Understanding the "Node" resolution system in TypeScript 3.9

This handbook explains that non-relative imports like import * from "banana" will recursively search the "node_modules" directory up to the parent directory.

Hence, it is essential to name the directory "node_modules".

If using Libman, while the fundamental theory of TypeScript depends on "node.js," sticking with the legacy and obsolete "Classic" resolution system is not advisable.

Ultimately, adjust the tsconfig.json to locate our "lib" directory or rename the directory to "node_modules" to align with the "Node" resolution system (Not recommended since we are using Libman, not Node).


2. Libman relies on the "lib" directory by default.

Due to the preceding reasons, there is a necessity for a "node_modules" directory instead.

The default directory named "lib" by Libman prevents the compiler from searching for libraries within that directory.


3. Directory names of libraries should match the ModuleName.

Upon utilizing non-relative imports like import * from "banana", the compiler attempts to find "./node_modules/banana.js(ts)" or "./node_modules/banana/*".

In my libman.config file, there is a declaration for typing (.d.ts) of popper.js version 1.X.

{
  "provider": "filesystem",
  "library": "lib_ManualInstallSources/popper_v1/",
  "destination": "lib/types/popper_v1/"
}

However, the "desitination" property is incorrect as "popper_v1."

For instance,

import * as Popper from "popper.js"
fails to locate this directory, highlighting the need to change the directory name to "lib/types/popper.js".


[How to resolve]

I have identified two approaches to rectify these issues.

  1. Modify the settings in tsconfig.json to enable the compiler to search the "lib" directory.
  2. Update the directory names of libraries via Libman to "node_modules" (Not recommended).

I recommend the first method because we are using Libman, not Node. While having the "node_modules" directory may create confusion implying the use of Node, transitioning to it can simplify the overall configuration.


1. Adjust the settings in tsconfig.json to allow the compiler to search the "lib" directory.

// tsconfig.json
{
  "compilerOptions": {
    "sourceMap": true,
    "target": "es5",
    "lib": [ "ES6", "DOM" ],
    "baseUrl": ".",
    "typeRoots": [
      "./node_modules/@types",
      "./lib/types"
    ],
    "paths": {
      "*": [ "lib/*", "lib/types/*" ]
    }
  },
  "exclude": [
    "node_modules",
    "wwwroot",
    "lib"
  ]
}
// libman.json
{
  "version": "1.0",
  "defaultProvider": "jsDelivr",
  "libraries": [
  ...
  ]
}

2. Rename the directory of libraries via Libman to "node_modules" (Not recommended).

{
  "compilerOptions": {
    "sourceMap": true,
    "target": "es5",
    "lib": [ "ES6", "DOM" ],
    "baseUrl": "."
  },
  "exclude": [
    "node_modules",
    "wwwroot",
    "lib"
  ]
}
{
  "version": "1.0",
  "defaultProvider": "jsDelivr",
  "libraries": [
  ...
  ]
}

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

Encountering a problem with the Typescript compiler due to the inclusion of the baseurl configuration

I am currently attempting to enable absolute imports in my React project, which is compiled using TypeScript. I have been advised to add the baseUrl config option to instruct the compiler where to search for files. However, upon compiling my code, I encoun ...

Prevent images in Bootstrap carousel from being cropped while adjusting device height and width

I am attempting to implement a responsive bootstrap carousel similar to the one showcased in the airbnb example. My challenge lies in ensuring that the carousel remains responsive across all device sizes. I have tried setting fixed height and width for bot ...

Is there a way to create a vibrant, multicolored background without the use of images?

I am currently developing a mock website and have encountered an issue. Here is the Wix webpage I am using as a reference. My goal is to create multicolored div boxes at the bottom of my webpage where I can overlay text. However, I am struggling to achieve ...

Utilizing Angular 5: Display a Loading Indicator while Searching using Async Pipe

As I work on incorporating a search field with async in Angular 5, I want the loading indicator to appear when the user starts typing in the search box and disappear once the results are fetched. However, following this approach led to the loading indicato ...

Embed the group icon within the upload file button

I've been attempting to create an input group that functions as a file upload button with an icon embedded. Despite my efforts, I haven't been successful with the following code: <div class="row"> <div class="col-xs-10 col-md-6"> ...

Creating external route links in Angular 2 app setup

I've been contemplating whether it's considered poor practice to define angular2 app router links outside of the app. Is there a more efficient way to accomplish this? Throughout the angular2 documentation, routing examples typically showcase li ...

Parameters for constructing classes in TypeScript

I've been exploring different coding styles in TypeScript recently. When it comes to initializing an object from a class, what are the advantages and disadvantages of these two code styles in TypeScript? class Class3 { // members private rea ...

Next.js not storing prop value in state variable

In my current project using Next.js, I am facing an issue with passing props from one component to another. These props include properties of a product such as name, ID, and quantity. This particular component is a Cart Component responsible for rendering ...

Error encountered while retrieving data from Firebase and storing it in an array within an IONIC application

I am currently working on a function that retrieves data from Firebase's real-time database and stores it in an array for mapping in React. However, I am encountering a TypeScript error that I'm having trouble resolving. The error message reads ...

"Implementing a retry feature for Angular http requests triggered by a button

Imagine having a situation where a component has a method that triggers an http request defined in a service. The observable is subscribed to within the component: Component: fetchData() { this.apiService.fetchDataFromServer().subscribe( respo ...

Is it possible to develop a synchronous function in Angular 2?

I've successfully stored some data in Ionic 2's Storage feature. import { Storage } from '@ionic/storage'; ... ... ... constructer(public storage: Storage){} this.storage.set('usertype', usertype); Next, I need to set up a ...

The compatibility between `webpack-streams` and `@types/webpack`

I encountered an issue with my gulpfile while building it with TypeScript. Everything was working fine until I included @types/webpack-stream. Suddenly, I started getting a series of errors that looked quite ugly: node_modules/@types/webpack-stream/index.d ...

Experimenting with Typescript, conducting API call tests within Redux actions, mimicking classes with Enzyme, and using Jest

I am facing an issue where I need to mock a class called Api that is utilized within my redux actions. This class is responsible for making axios get and post requests which also need to be mocked. Despite following tutorials on how to mock axios and class ...

Exploring the power of Supabase's two-tiered joins using TypeScript

After reviewing the documentation here, I managed to successfully implement the first level join (agent_profile) but encountered issues when trying to join the next level (agent_office). Although the query returns the correct data, both VS Code and my app ...

Check to see if the upcoming birthday falls within the next week

I'm trying to decide whether or not to display a tag for an upcoming birthday using this boolean logic, but I'm a bit confused. const birthDayDate = new Date('1997-09-20'); const now = new Date(); const today = new Date(now.getFullYear( ...

Solving the default font problem in Laravel

I've been working on a project using Laravel and Bootstrap 4. Recently, I decided to switch from the default Laravel font, Nunito, to Lato. So, I made the necessary changes in my app.css file: @import url(https://fonts.googleapis.com/css?family=Nun ...

Attention all beginners: there is an issue with the navigation bar where the section below is overlapping it. Additionally, assistance is needed in understanding how to set limits for

Greetings to all. I'm encountering an issue while setting up my first Bootstrap Nav bar. Although I've managed to make it work, the section right below it is overlapping the navbar (I can only see the navbar if I use a z-index of -1, but then the ...

The issue of Bootstrap 4.0 "Modal" not functioning properly when combined with Angular 4

Struggling to integrate a Bootstrap 4.0 modal into an Angular 4 project? The modal functions perfectly within a simple static HTML page: https://jsfiddle.net/Lq73nfkx/1/ <!-- MODAL --> <!-- Button trigger modal --> <button type="button" cl ...

Adding text color in bootstrap is an easy way to enhance the visual appeal

Utilizing Bootstrap 4. I am aware that it is feasible to modify the color of Bootstrap by using a variable file and importing it prior to Bootstrap themes: I have crafted the subsequent $theme-colors: ( 'primary': #3892e5, 'secondary ...

Are the Angular tests passing even before the asynchronous call has finished?

When running the following Angular (4) test for a service, it appears to pass before the Observable returns and hits the expect statement. it('should enter the assertion', inject( [ MockBackend, CellService ], ( backend: MockB ...