Search code examples
javascripttypescriptecmascript-6axiostypescript-compiler-api

how to declare a node import in typescript compiler to ignore it in compiled file?


Hello while trying to understand typescript and the typescript compiler a little bit better i tried a little web project.

The workflow is simple. The typescript compiler watches the src/jsfolder and compiles every *.tsfile into my dev_static/js folder as a *.jsfile and also replicate the folder structure.

From there my django dev server fetches the *.jsfiles if necessary. For example page_1.html needs the script <script type="module" src="{% static 'js/pages/page_1.js' %}"> </script>.

src/
   js/
      pages/page_1.ts
      pages/page_2.ts
      navbar/navbar.ts
      modules/some_modul.ts


dev_static/
          js/
            pages/page_1.js
            pages/page_2.js
            navbar/navbar.js
            modules/some_modul.js

.tsconfig

{
    "compilerOptions": {
        "outDir": "../dev_static/js",
        "removeComments": true,
        "target": "ES6",       
         "lib": [
            "es6",
            "dom",
            "es2015.promise"
        ],
        "allowJs": true,
        "checkJs": true,
        "moduleResolution": "node",
        "baseUrl": ".",
        "paths": {
            "~*": ["./*"],
            "@node/*": ["./node_modules/*"]
        },
    },
    // Input Dir
    "include": ["src/**/*"],
    "exclude": ["node_modules", "**/*.spec.ts"]
}

Problem

importing modules as ES6 works fine. But i am struggling to declare 3rd Party libraries like Axios in my typescript project. For Example to use the types and intellisense of axios i imported Axios as a Node Module like this:

axios_fetch.ts

import axios from '@node/axios'; 
import { graphUrl } from '../env/env.js'; 

Compiler Output:

axios_fetch.js

import axios from '@node/axios';
import { graphUrl } from '../env/env.js';

Of Course the Browser does not know how to resolve this: import axios from '@node/axios'; .

2127.0.0.1/:1 Uncaught TypeError: Failed to resolve module specifier "@node/axios". Relative references must start with either "/", "./", or "../".

Furthermore i load the axios min.version (or other 3rd Party Libraries) global in my dev server. Its embedded in a base template on which every other page is based on and every page will have <script type="module" src="{% static 'js/3rdParty/axios/axios.min.js' %}"> </script> in it by default.

dev_static/
          js/
            pages/page_1.js
            <...>
            3rdParty/axios/axios.min.js

Question

How can i tell the compiler not to compile the line import axios from '@node/axios'; in my typescript file? Because the Axios Library will be available or loaded global as a minified version in all my pages (templates). I only need this line so that typescript does not complain and has the types available.

What i need is that the typescript compiler does not process the "import" line for axios while compiling. Or in other words i need that node import only in dev-compile-time for type checking, interface etc. but not in finished javascript file or runtime.

axios_fetch.ts

    import axios from '@node/axios';// do not compile this. "axios" will be global available
    import { graphUrl } from '../env/env.js';

If i manually delete import axios from '@node/axios'; in my axios_fetch.js this it works.


Solution

  • Alright after some days of research i found this solution and it works for me. Typescript no longer complains or exports the types import line into my compiled file, while still having access to types and intelisense in my *.ts file.


    First i changed a bit in the tsconfig.json very important to declare "importsNotUsedAsValues":"remove".

    tsconfig.json

    {
        "compilerOptions": {
            // Output Dir
            "outDir": "../dev_static/js",
            "removeComments": true,
            // Compile to. What JS Versions.
            "target": "ES6",       
             "lib": [
                "es6",
                "dom",
                "es2015.promise"
            ],
            // allows also normal JS files
            "allowJs": true,
            // Normal JS file also be checked
            "checkJs": true,
            // important for import modules etc.
            "module": "es2015",
            "moduleResolution": "node",
            "importsNotUsedAsValues":"remove",
            "baseUrl": ".",
            "paths": {
                "~*": ["./*"],
                "@node/*": ["./node_modules/*"]
            },   
             "types": ["axios"]
    
        },
        // Input Dir
        "include": ["src/**/*"],
        "exclude": ["node_modules", "**/*.spec.ts"]
    }
    

    Then i imported only the needed type from the axios nodes version and declared it as a global. But you can also simply download the index.d.ts type file from the axios git repo and put into your folder. Remove "types": ["axios"] from the tsconfig and import with import {AxiosStatic} from './axios';

    In other words the first line imports types that i only need in this *.tsfile but not later in my compiled *.js file. The second import line imports a variable called graphUrl as an ES6 Module, that reference on the other hand i will need later in my compiled file.

    axios_fetch.ts

    import { AxiosStatic } from 'axios'; // import the specific types from nodes axios 
    import { graphUrl } from '../env/env.js'; // that some es6 module vars i need also later
    
    declare global {
        const axios: AxiosStatic ;
    } 
    
    // AXIOS Client
    export const clientA = axios.create({
        baseURL: graphUrl,
        headers: {
            'Content-Type': 'application/json',
            'X-CSRFToken': csrftoken,
        } });
    

    So by declare global typescript seems does not have to worry not to export const axios: AxiosStatic or to fulfill all type demands (importsNotUsedAsValues) because it now knows there will be a deposit on a global scale.

    axios_fetch.js

    import { graphUrl } from '../env/env.js';
    const csrftoken = getCookie(cookieName);
    export const clientA = axios.create({
        baseURL: graphUrl,
        headers: {
            'Content-Type': 'application/json',
            'X-CSRFToken': csrftoken,
        }
    });
    

    Now have it compiled without the import { AxiosStatic } from 'axios'; line of the types.