TypeScript - Module is undefined at runtime - javascript

I dont understand what i'm doing wrong. I've create a TypeScript project in VS2012, and created a file named "Vector.ts", in a sub-directory named "Physics":
// Module
module Physics {
// Class
export class Vector {
constructor(public x: number) { }
}
}
Also, I have the following app.ts file:
/// <reference path="Physics/Vector.ts" />
window.onload = () => {
var vector = new Physics.Vector(6);
};
The project is successfully compiled, but when i launch it, i get the following exception:
0x800a1391 - JavaScript runtime error: 'Physics' is undefined
I don't understand what am i doing wrong...
Thanks.

If you are using AMD style modules with a module loader such as Require.Js, you need an import statement. See Steve's accepted answer here: https://stackoverflow.com/a/14919495/1014822 Your code will look something like:
import Physics = module("Physics/Vector");
var vector = new Physics.Vector(6);
... and you won't need this: /// <reference path="Physics/Vector.ts" />
If you are not using a module loader, you just need to make sure you include your Vector.js output file somewhere in your html page, and make sure it loads before your app file. In this case, you use /// <reference path="Physics/Vector.ts" /> to tell TS where to find your module for intellisense etc. to work.

Just for completeness, if you're using System then you'd use the import function:
System.import("Physics/Vector");
If you're doing this for Angular 2 then you'd want to do this before your bootstrap import

Related

Consuming JavaScript code in TypeScript application

I'm learning TypeScript and as a practice I wanted to try to consume JavaScript code in my TS app.
For example, this is your .js file:
foo = function() {
console.log("imported from Test.js");
};
I have managed to make it work with the following code:
//Test.js
module.exports.foo = function() {
console.log("imported from Test.js");
};
//Test.d.ts
declare module 'Test' {
export function foo(): void;
}
//HelloWorld.ts
import * as t from './Test';
t.foo();
This code executes fine but produces the following error which I cannot get rid of:
Error:(1, 20) TS2306:File 'C:/Users/2512/Projects/TypeScript/Test.d.ts' is not a module.
Also, if module.exports is used in Test.js then foo() cannot be called in Test.js as foo(); as it produces a foo is not defined error.
My main question is, what is the most up-to-date practice to import .js code into .ts without making any modification to an existing .js file?
I've spent many hours looking for the answer but could not find an ideal solution. Thank you.
P.S. I have typings installed in the project so I believe /// <reference path="Test.d.ts" /> is not required in Test.ts.

How to import a namespace with using 'require'?

In some code I'm working on I have a mixture of Coffeescript, Javascript and Typescript files.
In my Typescript file, I access the type definitions using
/// <reference path="foo.d.ts" />
import {FooA, FooB} from "foo";
var a:FooA = new FooA() // etc...
This results in the Javascript
var foo_1 = require("foo");
var a = new foo_1.FooA();
Which is fine. However, my workflow is such that I don't use a module system. All the non-JS files are handled by Grunt and compiled to JS and then bundled together.
Ideally I would want my Typescript to compile to
var a = new FooA();
as I can guarantee they would be in the global namespace.
How can I do this?
Ideally I would want my Typescript to compile to ... as I can guarantee they would be in the global namespace. How can I do this?
I am sure you know that global is bad and susceptible to subtle ordering issues (beyond just name collision) : some notes
That said. A file will become a module as soon as you have a root level import or export (some docs).
So :
/// <reference path="foo.d.ts" />
import {FooA, FooB} from "foo";
var a:FooA = new FooA() // etc...
Should be something like:
/// <reference path="foo.d.ts" />
var a:FooA = new FooA() // etc...
i.e. FooA should be available globally. You need to review your foo.d.ts. This will help: https://basarat.gitbooks.io/typescript/content/docs/types/migrating.html

TypeScript, React and Gulp.js - defining react

I am trying to make a workflow, where I can write React modules using TypeScript and automatic compiling to JavaScript via Gulp.js. I am using TypeScript 1.6.2, gulp-react and gulp-typescript.
My .tsx file looks like this now:
/// <reference path="../../../../typings/react/react.d.ts" />
import React = __React;
interface HelloWorldProps {
name: string;
}
var HelloMessage = React.createClass<HelloWorldProps, any>({
render: function() {
return <div>Hello {this.props.name}</div>;
}
});
React.render(<HelloMessage name="helloooo" />, document.getElementById('test'));
My problem is this line: import React = __React;
When I leave it out, I get the error
error TS2304: Cannot find name 'React'.`
when compiling .tsx to .js (but it still compiles to JSX, and I can use the output). When I put it in, I can compile without errors, but when I try to use the file inside the browser, I get an Uncaught ReferenceError: __React is not defined, of course.
This is how my gulptask looks like:
gulp.task('gui-tsx', function () {
var tsResult = gulp.src(config.guiSrcPath + 'tsx/app.tsx')
.pipe(ts({
jsx: 'react'
}));
return tsResult.js.pipe(gulp.dest(config.guiSrcPath + 'jsx'));
});
Is there a workaround for this? Or am I missing something here?
Okay, I found a solution. First install the React global definition via tsd:
tsd install react-global
This will create a file, react-global.d.ts, in your typings directory, which you have to reference in you root component file (the path is relative, so adjust it to your needs):
/// <reference path="../../../../typings/react/react-global.d.ts" />
After that it compiles without errors.
where I can write react modules using typescript and automatic compiling to js via gulp
Highly recommend you don't use global modules. Instead compile with --module commonjs and embrace the react / webpack / nodejs ecosystem.
You can checkout an example application here : https://github.com/basarat/tsb/tree/master

How to import a js library without definition file in typescript file

I want to switch from JavaScript to TypeScript to help with code management as our project gets larger. We utilize, however, lots of libraries as amd Modules, which we do not want to convert to TypeScript.
We still want to import them into TypeScript files, but we also do not want to generate definition files. How can we achieve that?
e.g. The new Typescript file:
/// <reference path="../../../../definetelyTyped/jquery.d.ts" />
/// <reference path="../../../../definetelyTyped/require.d.ts" />
import $ = require('jquery');
import alert = require('lib/errorInfoHandler');
Here, lib/errorInfoHandler is an amd module included in a huge JavaScript library that we do not want to touch.
Using the above code produces the following errors:
Unable to resolve external module ''lib/errorInfoHandler''
Module cannot be aliased to a non-module type.
This should actually produce the following code:
define(["require", "exports", "jquery", "lib/errorInfoHandler"], function(require, exports, $, alert) {
...
}
Is there a way to import a JavaScript library into TypeScript as an amd Module and use it inside the TypeScript file without making a definition file?
A combination of the 2 answers given here worked for me.
//errorInfoHandler.d.ts
declare module "lib/errorInfoHandler" {
var noTypeInfoYet: any; // any var name here really
export = noTypeInfoYet;
}
I'm still new to TypeScript but it looks as if this is just a way to tell TypeScript to leave off by exporting a dummy variable with no type information on it.
EDIT
It has been noted in the comments for this answer that you can achieve the same result by simply declaring:
//errorInfoHandler.d.ts
declare module "*";
See the github comment here.
Either create your own definition file with following content:
declare module "lib/errorInfoHandler" {}
And reference this file where you want to use the import.
Or add the following line to the top of your file:
/// <amd-dependency path="lib/errorInfoHandler">
Note: I do not know if the latter still works, it's how I initially worked with missing AMD dependencies. Please also note that with this approach you will not have IntelliSense for that file.
Create a file in lib called errorInfoHandler.d.ts. There, write:
var noTypeInfoYet: any; // any var name here really
export = noTypeInfoYet;
Now the alert import will succeed and be of type any.
Typically if you just want to need a temporary-faster-solution, that could be done by defining a new index.d.ts in the root of the project folder, then make a module name like described inside package.json file
for example
// somefile.ts
import Foo from '#awesome/my-module'
// index.d.ts on #awesome/my-module
declare module '#awesome/my-module' {
const bind: any;
export default bind;
}
Ran into that that problem in 2020, and found an easy solution:
Create a decs.d.ts file in the root of your TS project.
Place this declaration:
declare module 'lib/errorInfoHandler';
This eliminates the error in my case. I'm using TypeScript 3.9.7

Typescript - module functions reference in different file - "could not find symbol"

Apologies if the answer to this is simple, or I've mis-read the typescript documentation, but..
I have a module:
module Utils{
export function MyFunction(str: string):string {
return // something to do with string
}
}
I want to use this in another .ts file (Clients.ts) so at the top I add a reference and try to use it:
/// <reference path="Utils.ts" />
Utils.MyFunction(str);
But get the following error:
/*
Compile Error.
See error list for details
[path]/Clients.ts(26,39): error TS2095: Could not find symbol 'Utils'.
[path]/Clients.ts(30,49): error TS2095: Could not find symbol 'Utils'.
error TS5037: Cannot compile external modules unless the '--module' flag is provided.
*/
Could anybody explain what I'm doing wrong?
Using VS2012, with Web Essentials and TypeScript 0.9.1
Thanks.
Found the answer myself. What I was actually looking for was a static method on a class. As per the below:
class Utils {
static MyFunction(str: string): string {
return //... do something with string
}
}
And this worked in the Client.ts
/// <reference path="Utils.ts" />
var x = Utils.MyFunction(str);
The error you are getting error TS5037: Cannot compile external modules unless the '--module' flag is provided. is not something you would get with your code.
You would get this only if you export something at the root level of your file. e.g.
export module Utils{ // Notice the export keyword
export function MyFunction(str: string):string {
return // something to do with string
}
}
In this case you are using an external module loader and typescript needs to know if its amd(requirejs/browser) or commonjs(node/server side)
PS: I did a video on the subject : http://www.youtube.com/watch?v=KDrWLMUY0R0&hd=1

Categories

Resources