Where does the "use strict" go when using TypeScript and AMD Modules - requirejs

I am using TypeScript version 1.0.1.0
When using TypeScript and AMD modules together, where exactly should I write the "use strict" statement? Should it go above or below the imports?
I can write it above the imports, so that this TypeScript code:
"use strict";
import Backbone = require('backbone');
class MyClass extends Backbone.View<Backbone.Model> { }
export = MyClass;
results in this JavaScript with the statement at the top of the file:
"use strict";
var __extends = this.__extends || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
};
define(["require", "exports", 'backbone'], function(require, exports, Backbone) {
var MyClass = (function (_super) {
__extends(MyClass, _super);
function MyClass() { _super.apply(this, arguments); }
return MyClass;
})(Backbone.View);
return MyClass;
});
Or I can put the "use strict" statement below my imports. So that this TypeScript:
import Backbone = require('backbone');
"use strict";
class MyClass extends Backbone.View<Backbone.Model> { }
export = MyClass;
Results in this Javascript with the statement at the top of the RequireJS function declaration:
var __extends = this.__extends || function (d, b) {
for (var p in b) if (b.hasOwnProperty(p)) d[p] = b[p];
function __() { this.constructor = d; }
__.prototype = b.prototype;
d.prototype = new __();
};
define(["require", "exports", 'backbone'], function(require, exports, Backbone) {
"use strict";
var MyClass = (function (_super) {
__extends(MyClass, _super);
function MyClass() { _super.apply(this, arguments); }
return MyClass;
})(Backbone.View);
return MyClass;
});
Which one is correct? TSLint does not report a violation even when the statement is missing entirely. Is that perhaps a bug in TSLint?

The first variation results in whole-script strictness:
"use strict";
import Backbone = require('backbone');
class MyClass extends Backbone.View<Backbone.Model> { }
export = MyClass;
The second limits the scope of strictness to just the (generated) function:
import Backbone = require('backbone');
"use strict";
class MyClass extends Backbone.View<Backbone.Model> { }
export = MyClass;
In practise, it makes little difference in your case as it is only difference between the strict declaration including the auto-generated "extends" code or not - and the auto-generated code is strict-compliant.

Related

How to define a class AND constants in a CommonJS module

I have seen this thread on how to share constants across CommonJS modules:
How do you share constants in NodeJS modules?
However, if I want the same file to also have a class which should be exposed in the module, then how do I achieve that?
If I do:
module.exports = class A { ... }
Then I "used" the module.exports object.
Is there a way to mix both class AND constants in the same file?
In es6, I would simple add the term "export" before each one...
module.exports = ... is a bad practice if there's a chance that a module can have more than one exported value.
There's already existing module.exports object that is aliased as exports, it's purpose is similar to named exports in ES modules:
exports.A = class A { ... };
exports.b = 'constant';
Got it to work.
In file X.js I write:
constant B = "value";
class A {
}
modules.exports = {
A: A,
B: B
};
In the client code I use:
const X = require('./X');
let a = new X.A();
This is fairly easy to figure out. Now, let's say you have a code like this.
export class A { }
export const y= 5;
Which you basically want. But this is same as
class A { }
const x = 5;
exports.A = A;
exports.x = 5;
Now, you can figure it out also. open up babel repl and paste your ES6 code there. It will give you the ES5 equivalent in the right pane.
I pasted that ES6 code and got back
"use strict";
Object.defineProperty(exports, "__esModule", {
value: true
});
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
var A = exports.A = function A() {
_classCallCheck(this, A);
};
var y = exports.y = 5;
Don't worry about _classCallCheck it is just a safeguard so that you cannot just call A() instead of new A()

How to create node.js module using Typescript

The very simple module that I've created to test the viability of this endeavor. Here is the beginning of SPServerApp.ts:
class SPServerApp {
public AllUsersDict: any;
public AllRoomsDict: any;
constructor () {
this.AllUsersDict = {};
this.AllRoomsDict = {};
}
}
module.exports = SPServerApp();
Then in my app, I have this require statement:
var serverapp = require('./SPServerApp');
I then try to access one of the dictionaries like so:
serverapp.AllUsersDict.hasOwnProperty(nickname)
But get the error:
TypeError: Cannot read property 'hasOwnProperty' of undefined
Can anybody see what I am doing wrong here?
Thanks, E.
The problem is that you forgot the 'new' keyword when calling the constructor. The line should read:
module.exports = new SPServerApp();
If you don't use new your constructor will be treated as a normal function and will just return undefined (since you did not return anything explicitly). Also 'this' will not point to what you expect within the constructor.
Omitting new in Node is actually quite common. But for this to work you have to explicitly guard against new-less calls in the constructor like so:
constructor () {
if (! (this instanceof SPServerApp)) {
return new SPServerApp();
}
this.AllUsersDict = {};
this.AllRoomsDict = {};
}
BTW, in TypeScript you can also use module syntax. The TS compiler will translate this into the export/require statements. With ES6 style modules your example would look like this:
export class SPServerApp {
public AllUsersDict: any;
public AllRoomsDict: any;
constructor () {
this.AllUsersDict = {};
this.AllRoomsDict = {};
}
}
export var serverapp = new SPServerApp();
In your other TS file you just import:
import { serverapp } from './SPServerApp';
serverapp.AllUsersDict.hasOwnProperty('something');

NodeJS module instances

I have the following code. I want to use the prototype keyword as I want to call method functions and not class methods, why does this give me an error? If I remove the prototype call this works. How can I write this code so I'm able to use instances not class methods?
//app.js
var MyTest = require('./MyTest')
var myTestInstance = new MyTest()
myTestInstance.testFunction(function(reply){
console.log(reply)
})
//MyTest.js
module.exports = function() {
function MyTest() {}
MyTest.prototype.testFunction = function(cb) {
cb('hello')
}
return MyTest
}
to have your app.js working as it is you need to replace the content of MyTest.js with the following:
function MyTest() {}
MyTest.prototype.testFunction = function(cb) {
cb('hello');
};
module.exports = MyTest;
As you have it in app.js you need a constructor and not a factory function.

Typescript AMD Module not returning anything

I am exporting a simple function inside of a "log.ts" file:
export function message(s : string) {
console.log(s);
}
This is imported by a file ("MyController.ts") in the same directory:
import log = module("./log");
class MyController {
a : string = "aaa";
constructor () {
log.message("hello world");
}
}
When compiled, I get the following JS:
define(["require", "exports", "./log"], function(require, exports, __log__) {
var log = __log__;
var MyController = (function () {
function MyController() {
this.a = "aaa";
log.message("hello world");
}
return MyController;
})();
})
//# sourceMappingURL=MyController.js.map
This define function should return MyController. Because it does not, the callback inside this snippet does not get anything for the controller parameter:
require(["MyController"], function (controller) {
theRoute.controller = controller;
defer.resolve();
$rootScope.$apply();
});
I can fix this by manually adding the return inside of the call to define, but this is not a good workaround because the JS is being outputted by the TS compiler.
Am I doing something wrong or is this a bug in typescript?
You should write:
import log = module("./log");
export class MyController { // <--- 'export'
a : string = "aaa";
constructor () {
log.message("hello world");
}
}
And:
require(["MyController"], function (controller) {
theRoute.controller = new controller.MyController(); // <--
defer.resolve();
$rootScope.$apply();
});
Starting in 0.9.x you'll be able to write export = MyController; at the bottom of the .ts file to make the class be the top-level exported object.

Writing a javascript library

I want to write a JS library and handle it like this:
var c1 = Module.Class();
c1.init();
var c1 = Module.Class();
c2.init();
And of course, c1 and c2 can not share the same variables.
I think I know how to do this with objects, it would be:
var Module = {
Class = {
init = function(){
...
}
}
}
But the problem is I can't have multiple instances of Class if I write in this way.
So I'm trying to achieve the same with function, but I don't think I'm doing it right.
(function() {
var Module;
window.Module = Module = {};
function Class( i ) {
//How can "this" refer to Class instead of Module?
this.initial = i;
}
Class.prototype.execute = function() {
...
}
//Public
Module.Class = Class;
})();
I don't have a clue if it's even possible, but I accept suggestions of other way to create this module.
I don't know if it's relevant also, but I'm using jQuery inside this library.
Usage:
var c1 = Module.Class("c");
var c2 = Module.Class("a");
var n = c1.initial(); // equals 'c'
c1.initial("s");
n = c1.initial(); // equals 's'
Module Code:
(function(window) {
var Module = window.Module = {};
var Class = Module.Class = function(initial)
{
return new Module.Class.fn.init(initial);
};
Class.fn = Class.prototype = {
init: function(initial) {
this._initial = initial;
},
initial: function(v){
if (v !== undefined) {
this._initial = v;
return this;
}
return this._initial;
}
};
Class.fn.init.prototype = Class.fn;
})(window || this);
This is using the JavaScript "Module" Design Pattern; which is the same design pattern used by JavaScript libraries such as jQuery.
Here's a nice tutorial on the "Module" pattern:
JavaScript Module Pattern: In-Depth

Resources