简体   繁体   中英

How do I import libraries in TypeScript in general?

I'm new to TypeScript and just digging into that rabbit hole. I think, I understand the concept so far but what I don't understand is how I finally make use of libraries (in my case D3 for manipulating SVG DOM). In vanilla Javascript I simply did it the old-fashion way by including the library and my main.js script one after another but as my project grows I want to use the advantages of TypeScript with a modular aproach.

Current issue is this browser error (Chrome):

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

Well, I know it points to my import statement but I cannot figure out how to solve it.

tsconfig.json

    {
        "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
        }
        // ,"files": [],
        // "include": [],
        // "exclude": []
    }

index.html (excerpt)

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

./src/fgn/fgn.ts

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

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

    // This is the desired functionality I want to gain: having access to d3 from global namespace (globalThis ?)
    d3.select('#testButton').on('click', () => {alert('button clicked!');});

    // Also this is not working. The browser complains the function is not defined.
    function unreachableFoo() { console.log('foo'); }

I have tried multiple tsconfig setups and changed the import to point to the "[root]/node_modules/d3/" (index.js) while enabling "allowJs" in tsconfig but this led to further issues as tsc somehow included the node_modules/@types/ path causing a mess-up and errors with the declaration files there.

Another attempt was to using webpack, setting up the package.json and building up the dependencies from there. Maybe I am on the right track with that but the browser error was still there.

What am I missing?

Welcome. The D3 documentation is going to be a little tougher to follow because it is using the import statement for JS and not TS. Try switching your import statement to

import { *desired methods* } from 'd3'; // there is no default d3 export

You will want to also undo your changes to your tsconfig.

Got it,

I simply missed the step of browserify. Instead of webpack, I am now using Rollup. For anyone encountering similar difficulties to getting started on that topic, here are some good explanations (take time to follow each):

How to Setup a TypeScript project using Rollup.js -- Rollup installation and required tsconfig.json setup; not all of the proposed installs are required, though.

Missing global variable names #162 -- rollup.config.js setup

@rollup/plugin-node-resolve -- usage of this plugin, in addition

Official rollup.js documentation -- RTFM

However, the Rollup specific fields in the rollup.config.js have changed over time, eg the 'entry' attribute was renamed to 'input'. Here's my current config following the above tutorials:

/* buil-in */
import resolve from '@rollup/plugin-node-resolve';
/*  Install both 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', // change this accordingly
        plugins: [
            resolve({
                jsnext: true,   
                main:   true,
                browser:true,         
            }),
            commonjs(),
            babel({
                exclude: 'node_modules/**',
            })
        ],
        output: {
            name: 'main',
            file: 'public/scripts/main.js', // change this accordingly
            /*  format: 'iife' wraps everything into a self-executing function
                (function () { ... }());
            */
            format: 'iife' // or 'cjs'
        }
    }
];

This does not yet minify the code, though. It's just a development setup but you can add a production one as well.

package.json build script

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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM