0

I'm relatively new to both Typescript and Javascript (and node.js), from a Java background, but learning fast the painful way. I recently converted from one giant Typescript file with a number of classes to using multiple classes. This took some research, and I don't claim to fully understand the 2+ different systems of Javascript imports. But I'm using the import {ClassName} from './{Classname}' syntax, and making sure that Classname starts with export class ClassName. This was initially working great. In particular, coming from a Java background and being dependent on compiler errors, I appreciated that Netbeans would detect errors in my importing, and tsc agreed. Add an import, try again, and everything made sense.

Until it stopped working, that is no errors were generated with wrong (?) code. At runtime I got ReferenceError: ClassToBeImportedis not defined. Sure enough, ClassToBeImported was not being imported. I expect adding import {ClassToBeImported} from './{ClassToBeImported} would solve it. (Am I right? Easier answered than tested in this case.) What bothers me is that this was a runtime error this time instead of an IDE/transpiler error.

While trying to come up with a minimal example, I think the problem is that the referenced file wasn't being exported. If I add/remove export from export class NeedsToBeImported the error comes/goes respetively.

This will generate an error (Cannot find name 'ClassToBeImported'.):

// in file MainClass.ts
export class MainClass{
    constructor(){
        let x = ClassToBeImported.SOME_FIELD;
    }
}

// in file ClassToBeImported.ts, same folder
export class ClassToBeImported{
    static SOME_FIELD : string = "data";
}

This will not, until runtime:

// in file MainClass.ts
export class MainClass{
    constructor(){
        let x = ClassToBeImported.SOME_FIELD;
    }
}

// in file ClassToBeImported.ts, same folder
class ClassToBeImported{
    static SOME_FIELD : string = "data";
}

So the primary question is what the heck is going on. ("Why does referencing a non-exported class not generate a transpilation error?") The secondary question is if there's anything I can do to make this "safer" on myself. If there's some option I can turn on in tsconfig.json (currently targeting es2015) to make it stricter it could be useful.

ojchase
  • 1,041
  • 1
  • 10
  • 22
  • what typescript version are you using? – shusson Apr 09 '19 at 07:14
  • 1
    If you are missing the `export`, TSC probably doesn't recognise `ClassToBeImported.ts` as a module. And as a script, the `class ClassToBeImported` is a global, so it works fine. You just have to included the script in your page alongside the others. – Bergi Apr 09 '19 at 07:30
  • @shusson Actually I'm not sure. `tsc --version` returns 2.6.1, but 3.4.2 is in my package.json. – ojchase Apr 09 '19 at 15:28

1 Answers1

0

There are two types of source files in JavaScript and TypeScript: scripts and modules.

I quote the handbook:

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).

For example, you could load the file ClassToBeImported.js in a <script> tag in a web page, and then the ClassToBeImported class will be available as a global variable.

Paleo
  • 21,831
  • 4
  • 65
  • 76