I encountered a problem where I have a class defined in one file and I'm attempting to create new objects from it to be loaded in my E2E $httpBackend. Unfortunately, the browser is unable to recognize it, causing the entire application to fail to load, with this error message appearing in the console:
Uncaught TypeError: app.Challenge is not a function
The TypeScript compiler (I'm using WebStorm for auto-compiling) does not show any errors and compiles successfully. Here's how the module containing the class looks like:
module app {
"use strict";
// interfaces here
export class Challenge implements IChallenge {
constructor(public answerString: string,
public difficulty: number,
public id: string,
public language: languages,
public name: string,
public tests: ITest[]) {
}
}
}
This is my mockBackend setup for my Angular app:
module app.development {
"use strict";
angular
.module("appMock", ["ngMockE2E"])
.run(challengeResourceMock);
challengeResourceMock.$inject = ["$httpBackend"];
function challengeResourceMock($httpBackend: ng.IHttpBackendService): void {
var challenges: app.IChallenge[] = [];
var challenge: app.IChallenge;
challenge = new app.Challenge( // <-- It says this is not a function!
"runThisFunction = function(str) {\n\treturn str.split('').reverse().join('');\n}",
1, "1", 1, "Reverse a String", [{
description: "make sure it reverses the string (e.g. 'start' will become 'trats)",
test: "function () {\n\tvar a = 'abcdef';\n\texpect(runThisFunction(a)).toEqual('fedcba');\n}"
}]);
challenges.push(challenge);
// more challenges are added to the list
// get all challenges
$httpBackend.whenGET("api/challenge").respond(200, challenges);
// pass through requests for anything else
$httpBackend.whenGET(/./).passThrough();
}
}
How do I resolve the error and make my application work smoothly with the mock backend?
UPDATE:
I've decided to remove TypeScript modules based on basarat's advice and switched solely to commonjs modules. Instead of using WebStorm's compiler, I'm now utilizing ts-loader with webpack. I also created a tsconfig file:
{
"compilerOptions": {
"target": "ES5",
"module": "commonjs",
"noImplicitAny": true,
"outDir": "./dist/tsOutput/",
"preserveConstEnums": true,
"removeComments": true,
"sourceMap": true
},
"exclude": ["node_modules", "trash", "coverage"]
}
Currently, everything is in the global space, even though it's not ideal while resolving conflicts due to the small size of the application. Despite these changes, I'm encountering a slightly different error message, resulting in the application failing to run.
Uncaught ReferenceError: Challenge is not defined
"Build" operation doesn't seem to be effective. There are no complaints from my IDE's inspector. It's as if the "class" keyword isn't functioning at all.
TEMPORARY HACK
After spending quite some time troubleshooting, I found myself running out of time. As a temporary solution, I replaced my Challenge objects with object literals:
module app {
"use strict";
angular
.module("appMock", ["ngMockE2E"])
.run(challengeResourceMock);
challengeResourceMock.$inject = ["$httpBackend"];
function challengeResourceMock($httpBackend: ng.IHttpBackendService): void {
var challenges: app.IChallenge[] = [];
var challenge: app.IChallenge;
challenge = {
answerString: "runThisFunction = function(str) {\n\treturn str.split('').reverse().join('');\n}",
difficulty: 1,
id: "1",
language: 1,
name: "Reverse a String",
tests: [{
description: "make sure it reverses the string (e.g. 'start' will become 'trats)",
test: "function () {\n\tvar a = 'abcdef';\n\texpect(runThisFunction(a)).toEqual('fedcba');\n}"
}]
};
challenges.push(challenge);
// additional obj literal challenges
// get all challenges
$httpBackend.whenGET("api/challenge").respond(200, challenges);
// pass through requests for anything else
$httpBackend.whenGET(/./).passThrough();
}
}
While I'll need to revisit this issue later on, I can continue progressing with my project for now.