This is part 13 of the tutorial series Learn TypeScript in Construct. This part continues on from part 12. So in case you missed it, see Learn TypeScript in Construct, part 12: Construct APIs.
We've covered a lot of the language basics of TypeScript in this guide, as well as a range of built-in features in the language, in the browser, and in Construct too. We're now coming towards the end of this guide, and there is only one last major topic to cover: modules. Once again there is a lot that we could potentially cover here, but we'll introduce the concept, cover the fundamentals, and also describe some aspects that are unique to Construct. In particular since scripts in event sheets are a concept unique to Construct, there's a specific way of dealing with that.
Modules
Remember that top-level variables and functions are scoped to the file. That means you can use them anywhere in that script file, but not in another script file.
One way to use things across files is to make them global, adding them as properties of globalThis
. However this has a number of problems. It quickly becomes disorganized, as you can end up with hundreds or even thousands of functions all in a single place. Further, it can cause name collisions: if you want to use two different libraries and they both try to define a global function with the same name, one will overwrite the other, and it will probably break things.
Modules solve these problems by providing a clean and organized interface for sharing things between TypeScript files. Each file is a self-contained module - its top-level variables and functions cannot be accessed outside the file. Another way of saying that is its contents are private to the module. If you want to expose something to be used outside of the file, it must be exported with the export
keyword. Then another file must import it with the import
keyword.
A simple export
For this example let's use a new empty project with two script files: main.ts and mymodule.ts. We'll export something from mymodule.ts and use it in main.ts. Download and open the project file below for this example.
Open the file mymodule.ts. Add the function below that just returns a string.
function GetMessage()
{
return "Hello world from mymodule.ts!";
}
Currently this function cannot be used outside of this file. However if we add the export
keyword, it becomes available to other files for importing. This goes at the start of the function, as shown below.
export function GetMessage()
{
return "Hello world from mymodule.ts!";
}
Script files can export as many things as they want. In this case we're just exporting a single function.
Now open main.ts. We want to call GetMessage()
, but it's still not available yet. To import everything from mymodule.ts, add the following line:
import * as MyModule from "./mymodule.js";
The *
means "everything", as MyModule
means to put everything in an object named MyModule
, and from "./mymodule.js"
indicates which file to load. So overall this means "import everything to an object named MyModule
from mymodule.js".
That's not a mistake - the file to import from does end with .js rather than .ts. Remember that TypeScript compiles your code to JavaScript: it effectively outputs .js files that have all the type annotations removed. TypeScript does not change the path of the script that is imported, and as everything ends up as JavaScript files before it's actually run, then you still have to use the .js file extension for imports. However TypeScript is aware of this and knows to find the types for type checking from the corresponding .ts file. In this guide we'll refer to importing mymodule.ts as that was where you wrote your code, but remember that the actual import
statement still must end with .js.
Note that the file path "./mymodule.js"
also starts with ./
. This is actually required and indicates it is a file (as things can be imported from other locations or in other ways).
Now everything exported from mymodule.ts is in an object named MyModule
. So our GetMessage()
function can be called with MyModule.GetMessage()
. Try the following code below for main.ts which logs the message to the console.
import * as MyModule from "./mymodule.js";
console.log(MyModule.GetMessage());
Preview the project and check the browser console, and you should see the message appear!
Congratulations - you've got your first import working.