I am learning typeScript with visual studio and trying to do a simple class export. I have seen this problem many times, but none of the solutions helped me. what am I doing wrong ?
still the same error "Uncaught ReferenceError: exports is not defined at..."
import { Address } from "./address";
class Customer {
protected name: string = "";
public addressObj: Address = new Address();
private _CustomerName: string = "";
public set CustomerName(value: string) {
if (value.length == 0) {
throw "Customer name is requaierd"
}
this._CustomerName = value;
}
public get CustomerName(): string {
return this._CustomerName;
}
}
export class Address {
public street1: string = "";
}
<!doctype html>
<html>
<head>
<title></title>
<meta charset="utf-8" />
</head>
<body>
<script src="address.js"></script>
<script src="Customer.js"></script>
<script>
try {
cust = new Customer();
cust.CustomerName = "doron";
cust.addressObj.street1 = "test"
} catch (ex) {
alert(ex);
}
</script>
</body>
</html>
what else am I not doing ?!?!
I've just solved this. Or rather I found a blog post that does https://blorkfish.wordpress.com/2012/10/23/typescript-organizing-your-code-with-amd-modules-and-require-js/. To follow the proper SO guidelines I will reproduce it here.
Why you get 'exports is undefined' is due to Visual Studio transpiling to use commonjs
modules. I looked at this for days trying different things and the message seemed to be that commonjs is the default and should "just work" (TM). But doesn't. I don't know what is missing - perhaps VS needs some include. I couldn't work out what.
The transpiled class using commonjs
will include lines like this at the top and bottom of the .js file:
Object.defineProperty(exports, "__esModule", { value: true });
...
exports.SpeciesClass = SpeciesClass;
This is your error.
The solution that worked for me was to use requirejs
. It is an implementation of AMD (http://requirejs.org/docs/whyamd.html). It still uses exports
but wraps it in a define
:
define(["require", "exports"], function (require, exports) {
"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
...
exports.SpeciesClass = SpeciesClass;
What follows is pretty-much the blog post https://blorkfish.wordpress.com/2012/10/23/typescript-organizing-your-code-with-amd-modules-and-require-js/. With some modifications for the most recent version of Typescript. Unfortunately where I'm working I don't have access to github (or anything like that) so I can only paste my files in here.
I also had to allow for some issues with Visual Studio. I found that despite configuring the project.csproj
's <TypescriptModuleKind>
to be AMD
, it seemed to always default to commonjs
. So I transpile manually and hope to find a solution to stop VS defaulting.
I created a tsconfig.json
file (tsc --init
) and set the module
to amd
. I added a "Files": ["*.ts"]
.
{
"compilerOptions": {
/* Basic Options */
"target": "es5", /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', or 'ESNEXT'. */
"module": "amd", /* Specify module code generation: 'none', commonjs
/* ... */
/* Strict Type-Checking Options */
"strict": true /* Enable all strict type-checking options. */
},
"Files" : ["*.ts"]
}
Commented out lines (with defaults) removed.
After starting the server, Visual Studio would transpile the files (using commonjs
module format). Requiring me to run tsc
to force the files to transpile to use the amd
module format. And it worked (no errors seen in the developer console).
First the files layout (from blogpost). What I have is the same except i've called my file index.html
as default.htm
reminds me of the bad ole days. You can get require.js
from http://requirejs.org/. And require.d.ts
from https://github.com/DefinitelyTyped/DefinitelyTyped/tree/master/types/requirejs (save the index.d.ts
as require.d.ts
).
export class Greeter {
element: HTMLElement;
span: HTMLElement;
timerToken: number;
constructor(element: HTMLElement) {
this.element = element;
this.element.innerText += "The time is: ";
this.span = document.createElement('span');
this.element.appendChild(this.span);
this.span.innerText = new Date().toUTCString();
}
start() {
this.timerToken = setInterval(() => this.span.innerText = new Date().toUTCString(), 500);
}
stop() {
clearTimeout(this.timerToken);
}
}
import { AppMain } from "./AppMain"
require(['AppMain'],
(main: any) => {
var appMain = new AppMain();
appMain.run();
}
);
import { Greeter } from "./classes/Greeter"
export class AppMain {
public run() {
// code from window.onload
var dummyEl: HTMLElement = document.createElement('span');
var theEl: HTMLElement | null = document.getElementById('content');;
var el: HTMLElement = theEl !== null ? theEl : dummyEl;
var greeter: Greeter = new Greeter(el);
greeter.start();
}
};
Or use:
var theEl: HTMLElement = document.getElementById('content');
var greeter: Greeter = new Greeter(theEl);
And just realise that what is called an 'error' when you transpile is just a warning!:
app/AppMain.ts(7,13): error TS2322: Type 'HTMLElement | null' is not assignable to type 'HTMLElement'.
Type 'null' is not assignable to type 'HTMLElement'.
No longer used
<html lang="en">
<head>
<meta charset="utf-8" />
<title>TypeScript HTML App</title>
<link rel="stylesheet" href="app.css" type="text/css" />
<!--
<script type="text/javascript" src="app/classes/Greeter.js"></script>
<script src="app.js"></script>
-->
<script data-main="app/AppConfig" type="text/javascript" src="lib/require.js"></script>
</head>
<body>
<h1>TypeScript HTML App</h1>
<div id="content"></div>
</body>
</html>
CommonJs isn't needed. Wrap all typescript in a common namespace and then export other namespaces, class, etc. Does offer intellisense:
MyClass1.ts
namespace GlobalNamespace {
export class MyClass1 {
prop1:string;
}
}
MyClass2.ts
namespace GlobalNamespace {
export class MyClass2 {
prop2:string;
}
}
Divide into namespace units:
SubClasses.ts
namespace GlobalNamespace {
export namespace SubNamespace1 {
export class SubClass1 {
myClass1: MyClass1;
}
}
}
namespace GlobalNamespace {
export namespace SubNamespace2 {
export class SubClass2 {
subClass1:SubNamespace1.SubClass1;
}
}
}
Instantiate SubClass2
var subClass2 = new GlobalNamespace.SubNamespace2.SubClass2();
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