Search code examples
javascripttypescriptsystemjs

ReferenceError with SystemJS


I'm using SystemJS as a module system to compile my TypeScript files but whenever I load the page in browser (via live-server) I get following error:

ReferenceError: Sensor is not defined
    at (index):17
    at <anonymous>

This is my index.html file:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Sensor</title>
</head>
<body>

    <input type="text" id="textField"/> 
    <p id="text"></p>

    <script src="node_modules/systemjs/dist/system.js"></script>
    <script>
        SystemJS.import('dist/index.js').then( function() {
            var textField = new Sensor(document.getElementById('textField')).setName('textField');
        }).catch(function(err) { console.log(err); });
    </script>
</body>
</html>

This is my tsconfig.json file:

{
    "compileOnSave": true,
    "compilerOptions": {
        "module": "system",
        "target": "es5",
        "outFile": "dist/index.js"
    },
    "files": [
        "./src/sensor.ts",
        "./src/signal.ts",
        "./src/signal_receiver.ts"
    ]
}

I checked output file and it looks like Sensor is defined:

System.register("sensor", ["signal", "signal_receiver"], function (exports_3, context_3) {
    ...
    exports_3("Sensor", Sensor);

Edit: I checked now and none of the functions were defined when I tried to call them.


Solution

  • I'm seeing two problems with your code. One is that you are using a bundle, but your code ignores that. Second is that you are not getting Sensor class from your module but instead you're getting it from the global space.

    In the code generated by tsc, the call for System.register has "sensor" for the first argument, which means that you are dealing with a bundle. This kind of call hardcodes the module name, and the module name here is "sensor". SystemJS bundles can be loaded with a script element so you could just add this after you load SystemJS:

    <script src="dist/index.js"></script>
    

    This will load the whole bundle and make all modules in it available for use.

    Then the generated code for your module exports the Sensor class as the Sensor field on your module. (That's what the code exports_3("Sensor", Sensor) does.) So you need to get it from the module when you use it. So the code should be:

    SystemJS.import('sensor').then(function(sensor) {
      var textField = new sensor.Sensor(document.getElementById('textField')).setName('textField');
    }).catch(function(err) { console.log(err); });
    

    In this code, I'm asking SystemJS to load the module named "sensor" which is the same name used by System.register, and I've added sensor to the argument list of the callback passed to .then and refer to the class as sensor.Sensor.