Issue creating a single .d.ts when using external modules - npm

I'm developing an NPM package using typescript. Within this package the TS files are setup as external modules. The compiler won't generate a single .d.ts for external modules. I'm trying to concat all tsc generated type definitions into a single .d.ts for the entire package.
I'm having issues laying out the single .d.ts file (following a similar approach to that used in grunt-dts-bundle). The condensed example below captures my issue.
Given this external module declaration and test file:
test.d.ts :
declare module "ExternalWrapper" {
export import Foo = require("FooModule");
}
declare module "FooModule" {
class Foo {
name: string;
}
export = Foo;
}
test.ts:
import externalWrapper = require( 'ExternalWrapper' );
var t = new externalWrapper.Foo();
Running tsc test.ts test.d.ts -m commonjs produces this error: TS2083: Invalid 'new' expression.
If you change 'test.ts' to look like this, importing 'FooModule' directly:
import Foo = require( "FooModule" );
var t = new Foo();
It compiles fine.
The compiler understands the type externalWrapper.Foo however it doesn't seem to represent it as the same type FooModule.Foo. There is something I'm not getting about how the compilers handles modules that are exported via 'export import'.
Failing the above I'll probably look to manually creating the .d.ts :(
Any help appreciated.

You are probably missing a reference tag:
/// <reference path="test.d.ts"/>
It works :

You should be able to fix this by modifying your .d.ts file to resemble the following:
declare module "ExternalWrapper" {
import FooModule = require("FooModule");
export var Foo: typeof FooModule;
}
declare module "FooModule" {
class Foo {
name: string;
}
export = Foo;
}
With the export import syntax the compiler was assuming you were exporting an instance of Foo, not Foo itself... a little quirky.

Related

How to use scalajs-bundler with client only app

In another question I was advised to use ScalaJS bundler to import NPM dependencies.
I would like to use some Javascript NPM packages in a simple client-only web application. There is an example called static which shows this.
My changes to the example:
Add into build.sbt:
npmDependencies in Compile += "esprima" -> "3.1.3"
Add into Main.scala:
import Esprima._
import JsonToString._
val code = "answer = 42"
val tokens = tokenize(code)
val tokensStr = tokens.json
Change in Main.scala: "This is bold" into s"This is bold $tokensStr"
Facade (a bit simplified, for full a version see GitHub):
import scala.scalajs.js
import scala.scalajs.js.annotation.JSName
#JSName("esprima")
#js.native
object Esprima extends js.Object {
def tokenize(input: String, config: js.Any = js.native, delegate: String => String = js.native): js.Array[js.Any] = js.native
def parse(input: String, config: js.Any = js.native): js.Dynamic = js.native
}
When running the html generated with fastOptJS::webpack the error is:
Uncaught TypeError: Cannot read property 'tokenize' of undefined
Inspecting the static-fastopt-bundle.js shows esprima is used, but its js is not bundled.
What other steps are needed to add dependencies into a client-only web page?
As described in this part of the documentation, you have to use #JSImport in your facade definition:
#JSImport("esprima", JSImport.Namespace)
For reference, #JSName defines a facade bound to a global name, while #JSImport defines a facade bound to a required JavaScript module.

Can't use external library in my app

I created a Gui library that works fine when i test it from within the project. Now i want to use it as a library, for my sound generation application.
Seems simple, but i couldn't get anything despite many changes in my references or compiler options...
I use 1.6.2 version of typescript, target es5, use commonjs formodule in both tsconfig.json files . moduleResolution is classic.
I don't know if that matters, but i use experimentalDecorators and i output declaration file and inlined source map.
What i have so far is like (simplified version):
••• Library files •••
shapes.ts
shapes/rect.ts
shapes/roundrect.ts
shapes.ts is the main module. Since i've read that files are already modules, i did not use the modulekeyword.
// shapes.ts
/// <reference path="./shapes/rect.ts"/>
/// <reference path="./shapes/roundrect.ts"/>
export * from "./shapes/rect.ts";
export * from "./shapes/roundrect.ts"
--
// rect.ts
export class Rect {
x : number;
y : number;
...
}
--
// roundrect.ts
/// <reference path="./rect.ts"/>
import {Rect} from "./rect.ts";
export class RoundRect extends Rect {
cornerRadius : number;
...
}
••• App files •••
for the App file, i made many attemps, i would like to be able to write :
var MyRect = new Rect();
or :
var MyRect = new Shapes.Rect();
So i tried a lot of import syntax, since no two blogs or docs says the same about this syntax :
import * as Shapes from '../../shapes/dst/shapes';
Or
import Shapes = require('../../shapes/dst/shapes');
Or
import {Rect, RoundRect} from '../../shapes/dst/shapes';
Or
var Shapes = require('../../shapes/dst/shapes');
( Or all above examples from the src and not the dst folder) .
All those examples get marked as a wrong path in the editor.
I also tried all examples above with or without :
/// <reference path="../../shapes/rect.ts"/>
Rq the path is marked correct with reference, but when using a reference path, there are a lot of 'Cannot find module' errors.
So bottom line, i always get, for the module import, the same error :
Cannot find module '../../shapes/dst/shapes'
¿¿¿ How can i use my lib ???
If you have multiple classes exported inside a file, it makes sense to use a module.
If you'd rather export a class as a module itself, you can try export =
Example:
class RoundRect {
....
}
export = RoundRect;
http://www.typescriptlang.org/Handbook#modules-export-

Import an AMD JS library in a TypeScript file

I'm stuck with the right way to import an AMD JavaScript library (https://github.com/dcodeIO/bytebuffer.js) into a TypeScript file.
I found its - not up-to-date - type definition (https://github.com/SINTEF-9012/Proto2TypeScript/commit/0889dccbf6048f116551a73e77d75dd83553cfe6), but actually I was not able to find a way to use it and have the library loaded by RequireJS.
This is the code I'm using:
/// <amd-dependency path="Scripts/bytebuffer" />
var ByteBuffer = require( 'Scripts/bytebuffer' );
import protocols = require( 'protocols' );
export class Pippo
{
readPayload( payload: ArrayBuffer, ECType: string ): any
{
var ECStruct = new protocols.ECStruct( ECType );
var bb = new ByteBuffer()
.writeIString( "Hello world!" )
.flip();
console.log( bb.readIString() + " from bytebuffer.js" );
}
}
The two modules protocols and bytebuffer are loaded correctly, but actually I cannot see members of instance bb in Visual Studio. If I put the line
/// <reference path="scripts/typings/bytebuffer/bytebuffer.d.ts" />
and comment
//var ByteBuffer = require( 'Scripts/bytebuffer' );
of course I can see methods and properties of bb, but the module is not loaded at runtime.
Is there a way to have the ByteBuffer.js loaded by RequireJS with the possibility to see its members in VS?
Thanks
There is a syntax for declaring the interface of external modules:
declare module 'amd/module/name' {
// module definition, probably with:
exports = thingToExport;
}
In your case it should probably be:
declare module 'Scripts/bytebuffer' {
exports = ByteBuffer;
}
Put this after the bytebuffer.d.ts file!!! Also see "Writing .d.ts files" in the handbook.
In my case the /// <amd-dependency> and /// <reference> stuff were also redundant - you may want to try it too, to simplify your code.

Reference a class' static field of the same internal module but in a different file?

I'm using TypeScript and require.js to resolve dependencies in my files. I'm in a situation where I want to reference a static field of a class in an other file, but in the same internal module (same folder) and I am not able to access it, even if the Visual Studio pre-compiler does not show any error in my code.
I have the following situation :
Game.ts
class Game {
// ...
static width: number = 1920;
// ...
}
export = Game;
Launcher.ts
/// <reference path='lib/require.d.ts'/>
import Game = require("Game");
var width: number = Game.width;
console.log(width); // Hoping to see "1920"
And the TypeScript compiler is ok with all of this. However, I keep getting "undefined" at execution when running the compiled Launcher.ts.
It's the only reference problem I'm having in my project, so I guess the rest is configured correctly.
I hope I provided all necessary information, if you need more, please ask
Any help is appreciated, thanks !
Your code seems sound, so check the following...
You are referencing require.js in a script tag on your page, pointing at Launcher (assuming Launcher.ts is in the root directory - adjust as needed:
<script src="Scripts/require.js" data-main="Launcher"></script>
Remove the reference comment from Launcher.ts:
import Game = require("Game");
var width: number = Game.width;
console.log(width); // Hoping to see "1920"
Check that you are compiling using --module amd to ensure it generates the correct module-loading code (your JavaScript output will look like this...)
define(["require", "exports", "Game"], function (require, exports, Game) {
var width = Game.width;
console.log(width); // Hoping to see "1920"
});
If you are using Visual Studio, you can set this in Project > Properties > TypeScript Build > Module Kind (AMD)
If you are using require.js to load the (external) modules, the Game class must be exported:
export class Game {}
If you import Game in Launcher.ts like
import MyGame = require('Game')
the class can be referenced with MyGame.Game and the static variable with MyGame.Game.width
You should compile the ts files with tsc using option --module amd or the equivalent option in Visual Studio

How should I access a module internal variable across typescript module fragments?

I have a typescript module that is split across two files,
and tsc (version 0.9.1.1) compiled it without errors, and the produced code ran correctly.
Here is a summary of the source file for my module:
split_module_example.ts:
//file: orders.part1.ts
module Orders { // first part of Orders
export var msg : string;
// set orders here
msg = 'hello';
}
//file: orders.part1.ts
module Orders { // second part of Orders
export var msg : string;
// reference orders here
console.log('orders=' + msg);
}
the compiler generates this javascript, which looks correct to me:
//file: orders.part1.ts
var Orders;
(function (Orders) {
Orders.msg;
Orders.msg = 'hello';
})(Orders || (Orders = {}));
//file: orders.part1.ts
var Orders;
(function (Orders) {
Orders.msg;
// reference orders here
console.log('orders=' + Orders.msg);
})(Orders || (Orders = {}));
I just upgraded my TypeScript compiler from 0.9.1.1 to 0.9.5.0.
But now when I run tsc:
tsc --out split_module_example.js split_module_example.ts
it issues this error:
split_module_example.ts(9,16): error TS2000: Duplicate identifier 'msg'.
However, the code still runs correctly.
I wonder if I'm doing something wrong, or if there was a bug introduced in the 0.9.5.0 compiler.
If I'm doing something wrong, what is the correct way to reference a module internal variable across module fragments?
If the compiler is wrong, is there a workaround?
You should only have the variable declared in exactly one location. Just remove the var declaration from all but one of the modules and everything will work as expected.