What is the standard method for importing libraries in TypeScript?

As a newcomer to TypeScript, I find myself delving into the depths of this new world. While I grasp the concepts thus far, I am struggling with incorporating external libraries (specifically D3 for manipulating SVG DOM) into my project. In traditional vanilla Javascript, I would simply include the library and my main.js script one after another. However, as my project expands, I aim to utilize TypeScript's advantages in a more modular approach.

The current issue I am facing is a browser error in Chrome:

Uncaught TypeError: Failed to resolve module specifier "d3". Relative references must start with either "/", "./", or "../"

I understand that it points to my import statement, but I cannot seem to find a solution to resolve it.

In my tsconfig.json file, I have the following setup:

    {
        "compilerOptions": {
            "target": "ES5",'ESNEXT'. */
            "module": "ESNext",
            "declaration": true,
            "outDir": "./dist/fgn/",
            "rootDir": "./src/fgn/",
            "strict": true,
            "allowSyntheticDefaultImports": true,
            "esModuleInterop": true,
            "skipLibCheck": true, // required to avoid checking d3 type definitions
            "forceConsistentCasingInFileNames": true
        }
    }

An excerpt from my index.html file:

    <head>
        <script src="../dist/fgn/fgn.js" type="module"></script>
    </head>
    <body>
        <button id="testButton" onClick="unreachableFoo();">Test Script</button>
    </body>

Within my ./src/fgn/fgn.ts file:

    /* Assuming I want to use the whole library as documented by Mike Bostock.
       However, this import statement throws an error in the browser when transpiled
       to JavaScript */
    import * as d3 from "d3"; // points to '[root]/node_modules/@types/d3' (index.d.ts)

    console.log('script is running...');

    // This desired functionality aims to access d3 from the global namespace 
    d3.select('#testButton').on('click', () => {alert('button clicked!');});

    // Unfortunately, this also does not work as intended. The browser claims the function is not defined.
    function unreachableFoo() { console.log('foo'); }

Despite various attempts with different tsconfig setups and changing the import path to "[root]/node_modules/d3/" (index.js) while enabling "allowJs" in tsconfig, I faced further issues as tsc somehow included the node_modules/@types/ path, resulting in confusion and errors with declaration files there.

Another approach I tried was utilizing webpack, setting up the package.json, and managing dependencies from there. Although I may be on the right track with this method, the browser error persisted.

What could I possibly be overlooking?

Answer №1

Ah, I see now,

I overlooked the browserify step and switched from webpack to Rollup instead. For those struggling with similar issues when starting out, here are some valuable resources to guide you through it (be sure to follow each one carefully):

Setting up a TypeScript project using Rollup.js -- Includes Rollup installation and necessary tsconfig.json setup; not all suggested installations are essential.

Resolving global variable names #162 -- Instructions for configuring rollup.config.js

@rollup/plugin-node-resolve usage -- Explains how to use this plugin effectively

Official rollup.js documentation -- Don't forget to refer to the official guides!

However, keep in mind that the Rollup specific fields in the rollup.config.js file have evolved over time, like changing 'entry' to 'input'. Here is my current configuration after following the above tutorials:

/* built-in */
import resolve from '@rollup/plugin-node-resolve';
/* Install these plugins:
    npm i @rollup/plugin-babel @rollup/plugin-commonjs --save-dev
*/
import commonjs from '@rollup/plugin-commonjs';
import babel from '@rollup/plugin-babel';

export default [
    {
        input: 'src/scripts/main.js', // Adjust as needed
        plugins: [
            resolve({
                jsnext: true,   
                main:   true,
                browser:true,         
            }),
            commonjs(),
            babel({
                exclude: 'node_modules/**',
            })
        ],
        output: {
            name: 'main',
            file: 'public/scripts/main.js', // Adjust as needed
            /* format: 'iife' wraps everything into a self-executing function
               (function () { ... }());
            */
            format: 'iife' // or 'cjs'
        }
    }
];

This setup does not include code minification yet; it's more of a development environment, but you can incorporate a production setup as well.

Update your package.json build script accordingly

  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "build": "tsc -b && rollup -c rollup.config.js"
  }

Answer №2

Hello there! Navigating through the D3 documentation may pose a challenge as it uses import statements for JavaScript instead of TypeScript. Consider modifying your import statement to

import { *desired methods* } from 'd3'; // note that d3 does not have a default export

Additionally, make sure to revert any changes made to your tsconfig file.

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

How can I execute a StoredProcedure using JavaScript?

I have a form with an email field and label <asp:TableRow runat="server"> <asp:TableCell runat="server"> <asp:TextBox runat="server" ID="txtUserEmail" onfocusout="emailVerification()" CssClass="forTe ...

Dynamic Interaction between Dropdown Menus in HTML Form

A question was posed by me 2 hours ago which got resolved: Previous Question Solved However, upon implementing it in my code, I am facing issues as evidenced here: http://jsfiddle.net/7YeL6/5/ The problem arises when only the dropdown with vehicles appea ...

Error retrieving user by provider account ID using Google and Firebase adapter with Next Auth

Encountering an issue while trying to integrate Google Provider with Firebase Adapter in Next Auth. Upon selecting an account, the following error is displayed: Running Firebase 9 TypeError: client.collection is not a function at getUserByProvider ...

Select a randomly generated number from an array, which dynamically updates every time the browser is refreshed

I recently completed a project in Angular that utilizes the TMDB API. The project is nearly finalized, but I have a desire to implement a change where the background image (backdrop_path) and other elements shift each time the browser is reloaded. Curren ...

What could be the reason for only one of my states being modified when I call my function?

Currently, I have a single state in React.js consisting of two key-value pairs for length validation and character validation: const [validation, setValidationState] = useState({ lengthValidation: "", characterValidation: "", }); These states are e ...

Angular Persistent States in Angular version 2 and beyond

Currently, I am in the process of transitioning an Angular 1.5.X application to Angular 4. Within my app, I incorporate Angular Ui-Router Sticky State from https://github.com/ui-router/sticky-states to prevent loss of content within my view when navigating ...

Exclude files from all folders except one in gulp source

This is the structure of my folders: views | - core | | | -core.module.js | core.controller.js | some.js | - home | -home.module.js home.controller.js somemore.js ... ... In my gulp file, I am looking to include all js files from the views ...

Executing Selenium tests: utilizing the webdriver.wait function to repeatedly call a promise

Currently, I am using Selenium ChromeDriver, Node.js, and Mocha for testing purposes... I am facing a dilemma at the moment: The driver.wait function seamlessly integrates with until. I have a promise, which we'll refer to as promiseA. This pro ...

Mongoose doesn't support saving extensive text-data

I am facing a challenge while trying to save an extensive text into my mongodb database as it keeps crashing. I am in the process of creating a snippet manager and below you can find the error code I encountered: { [MongoError: Btree::insert: key too larg ...

Error when accessing JSON property in Angular with Ionic 2: A Strange TypeError

I have implemented a provider in my Ionic project to fetch the user object from storage. Below is the code: import { Injectable } from '@angular/core'; import { Storage } from '@ionic/storage'; @Injectable() export class ApiProvider { ...

Transform the CSS href attributes to different HTML pages when clicked

One interesting feature I am trying to implement on my website is the ability for users to select a color theme for their browsing experience. I have successfully created different themed external CSS files and even developed a function to seamlessly switc ...

Vue router adds hashes to paths automatically

I am currently developing a web application using Vue.js. I have implemented the vue.js webpack template and incorporated the fullpage.js framework with jQuery in my main.js file. The anchor feature of fullpage.js is utilized on my contactForm component to ...

I want to know the most effective way to showcase particular information on a separate page using Angular

Recently, I've been working with a mock json file that contains a list of products to be displayed on a Product page. My goal is to select a specific product, such as 'Product 1', and have only that product's information displayed on th ...

Pause execution of javascript function for a short period

When the button is clicked, my script executes the function manage($n) $onclick = "manage('$n');"; However, I also want to refresh the page immediately after it is clicked. $onclick="window.location.reload(true);manage('$n')"; Altho ...

Sign in and view SESSION data on the current page without any need to refresh the

My website currently features a login form at the top of each page for users to input their username and password. Once the submit button is clicked, I utilize jQuery AJAX method to send the data to login.php without refreshing the page. Here, the credenti ...

A beginner's guide to implementing InstancedBufferGeometry in threejs

I am encountering an issue where the polygon is not being displayed when using InstancedBufferGeometry, even though it is shown when using BufferGeometry. Can anyone help me understand why the code below is not functioning as expected? Please provide gui ...

Prevent horizontal swiping in an angular bootstrap carousel

How can I deactivate the ng-swipe-right and ng-swipe-left functionalities for an Angular Bootstrap carousel? I attempted the following approach: Once the carousel is loaded: $timeout(function() { angular.element('.carousel').attr('ng-swip ...

How can JavaScript be used to show a hidden element when a checkbox is selected?

I'm having trouble with a form on my website that has a dropdown box initially hidden using CSS (display: none;). I want to make this dropdown visible (display: inline;) when a checkbox from another element is checked. Can anyone suggest a solution fo ...

Populate the database with values when the button is clicked

Hello, I encountered an issue with my code where it is adding empty values to the database when attempting to enter input text values. I am using PHP and MySQL for this task. <html> <body> <input type="text" name="value" /> <input ...

Undefined is returned when exporting an item from the function called 'this'

Here we have two examples of JavaScript functions. In the first one, console.log(this) works as expected and returns methods, variables, etc. function foo() { console.log(this); } foo(); However, in the second example: export const something = ' ...