I have a Project (Existing Project) for which frontend is writen in namespaced typescript. I cannot rewrite all typescript file from namespaced approach to export/import es6 syntax.
However the below code is working fine. and no issue if i add my new ts module or react component as far i wrap it in namespace and call it by Class or with namespace prefix if its in other namespace.
Issue is i cannot use external modules with import statement.How can i use..?since import statement is throwing error.
To be more specific for below code i wanted to use react-redux,
When i check the node_moduels folder i saw @types folder from where the React namesapce is referred I Assume Due to this line in tsconfig
"typeRoots": [
"./node_modules/@types/"
]
But when i install npm install --save @types/react-redux
it also created react-redux folder with index.ts under @types folder in node modules. but it doesnt have the Namespace export lines how the React type file has some thing like below.
export as namespace React;
declare namespace React {
....
}
Ultimately..How can i use third party node moudles, especially react-redux in this project. Or any simple node module and access it in any ts file simple moudles such as "react-bootstrap" Below is the simple ts file for react componnet wrapped in namesapce whihc is working fine (except import staement)
import { createStore } from 'redux'; //if i add this line this is throwing error.
namespace Profile.Sample {
import { createStore } from 'redux'; //this too throwing error, without these lines my code is working fine.
export class Profiles extends React.Component<any> {
constructor(props) {
super(props);
this.state = { brand: "Ford" };
}
render(): React.ReactNode {
return (
<sect
<div className="container-fluid">
<div className="row">
<div className="col-lg-12">
<div className="main-title">
<h2>Profiles</h2>
<p>Lorem ipsum dolor sit amet, consectetur adi</p>
</div>
</div>
</div>
</div>
</section>
);
}
}
}
Below is my tsconfig
{
"compileOnSave": true,
"compilerOptions": {
"preserveConstEnums": true,
"experimentalDecorators": true,
"declaration": true,
"emitBOM": true,
"jsx": "react",
"noEmitHelpers": true,
"inlineSourceMap": true,
"inlineSources": true,
"outFile": "wwwroot/Scripts/site/Profiles.js",
"skipLibCheck": true,
"skipDefaultLibCheck": true,
"target": "es5",
"typeRoots": [
"./node_modules/@types/"
]
}
}
I know namespace is not the recommended approach going forward..but this is an existing project and cannot rewrite all files from namespace to import/export statements.
via npm. You can use npm to install TypeScript globally, this means that you can use the tsc command anywhere in your terminal. To do this, run npm install -g typescript . This will install the latest version (currently 4.7).
In TypeScript, just as in ECMAScript 2015, any file containing a top-level import or export is considered a module. Conversely, a file without any top-level import or export declarations is treated as a script whose contents are available in the global scope (and therefore to modules as well).
A module can be created using the keyword export and a module can be used in another module using the keyword import . In TypeScript, files containing a top-level export or import are considered modules. For example, we can make the above files as modules as below. console.
Namespaces and Modules. A note about terminology: It’s important to note that in TypeScript 1.5, the nomenclature has changed. “Internal modules” are now “namespaces”. “External modules” are now simply “modules”, as to align with ECMAScript 2015’s terminology, (namely that module X { is equivalent to the now-preferred namespace X {).
We have succeeded in writing and publishing an npm module in TypeScript. The great thing that we achieved here is that our module can now be seamlessly used in JavaScript or TypeScript projects without any need of running. Feel free to reach out if you have any problems.
Namespaces are a TypeScript-specific way to organize code. Namespaces are simply named JavaScript objects in the global namespace. This makes namespaces a very simple construct to use. Unlike modules, they can span multiple files, and can be concatenated using outFile .
Namespaces are simply named JavaScript objects in the global namespace. This makes namespaces a very simple construct to use. They can span multiple files, and can be concatenated using --outFile.
Ok, let's make it runnable step by step:
Although you did not state it explicitly, I assume you get the error message Cannot compile modules using option 'outFile' unless the '--module' flag is 'amd' or 'system'.
. The option outFile
generates one master file with all your code concatenated in it. Since you are using "target": "es5"
in your tsconfig.json
, the default value for module
is commonjs
. commonjs
is the module syntax widely used for node.js (var x = require('x')
/ exports.x = x
) and this syntax does not support merging code into one file, therefore it is prohibited. But you want to use your code in the browser, so commonjs
is not supported there anyways. So the first thing to do is
Insert "module": "AMD"
into your tsconfig.json
file.
AMD is a module syntax usable in the browser. You can also use "UMD"
, which is just an extension, so that the module supports AMD
and commonjs
modules.
To avoid some more configuration later on, you should also
Change "outFile": "wwwroot/Scripts/site/Profiles.js"
to "outDir": "wwwroot/Scripts/site"
in your tsconfig.json
file.
Setting module
to AMD
changes the default of moduleResolution
from node
to classic
, but that's not good, because then import {createStore} from 'redux'
will fail with the error message Cannot find module 'redux'. Did you mean to set the 'moduleResolution' option to 'node', or to add aliases to the 'paths' option?
. Therefore
Include "moduleResolution": "node"
into your tsconfig.json
file.
In your code you define a class which extends another base class. If you transpile this inheritance, a special function __extends
is required. With the current setup this function is not generated by typescript and you get the error Uncaught ReferenceError: __extends is not defined
. Therefore
Remove "noEmitHelpers": true
.
Now all your files can be transpiled to AMD modules. But to use those modules, you need a module loader. The most popular one is require.js. To use it,
Insert <script data-main="setup" src="https://cdnjs.cloudflare.com/ajax/libs/require.js/2.3.6/require.min.js" integrity="sha512-c3Nl8+7g4LMSTdrm621y7kf9v3SDPnhxLNhcjFJbKECVnmZHTdo+IRO05sNLTH/D3vA6u1X32ehoLC7WFVdheg==" crossorigin="anonymous"></script>
into your HTML file.
You can also download it and serve it yourself. data-main="setup"
means that after require.js has been loaded, the script setup.js
is executed. This script is created in the next step.
require.js needs some configuration to find all the modules. So
Create wwwroot\Scripts\site\setup.js
:
requirejs.config({
appDir: ".",
paths: {
'react': ['./node_modules/react/umd/react.production.min.js', 'https://unpkg.com/react@16/umd/react.production.min'],
'react-dom': ['./node_modules/react-dom/umd/react-dom.production.min.js', 'https://unpkg.com/react-dom@16/umd/react-dom.production.min'],
'redux': ['./node_modules/redux/dist/redux.min.js', 'https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min'],
},
});
requirejs(['entryPoint'], function() {
console.log("Entry point 'index' has been loaded!");
return {};
});
In the first part require.js is configured. Especially, the locations of external modules (modules installed via npm
) are defined. Here the locations of react
, react-dom
and redux
are set to the locations in the node_modules
folder with external files from content delivery networks (CDN) as backups. You can also remove one of the locations. They are requested from left to right and moving on if one request fails. If you use the locations in your node_modules
folder, you must serve them from your webserver as well!
In the second part the module entryPoint
is executed. This is the entry point to your app. Change the name to whatever you want to be your entry point. If you want the module defined in the file someOtherFile.js
to be the entry point, then write requirejs(['someOtherFile'], ...
.
To transpile all files run
tsc --project tsconfig.json
.
Serve all files in the directory wwwroot/Scripts/site
including your HTML file. For testing purposes you can use
npx serve
.
You can see the slightly modified code here: https://codesandbox.io/s/elated-fermat-ie2ms?file=/src/index.tsx.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With