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/js
folder and compiles every *.ts
file into my dev_static/js
folder as a *.js
file and also replicate the folder structure.
From there my django dev server
fetches the *.js
files 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"]
}
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:
import axios from '@node/axios';
import { graphUrl } from '../env/env.js';
Compiler Output:
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
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.
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.
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 *.ts
file 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.