Referencing requirejs optimized typescript classes - requirejs

I am switing to using AMD compilation rather than typescript internal modules.
I have a project full of typescript classes and interfaces that I have successfully optimized into a requirejs file full of requirejs defines.
for example
class A {
...
}
export A;
Other classes reference the file and import the class fine.
In another project I pull in the R.js optimized file using bower and reference it in require_config.js and load the file ok.
Within this other project I want Class B to reference class A but class B is not in the file path.
What do I need to do? I guess I need to generate d.ts files that I reference in Class B but how do I do import ClassA = require("ClassA") when ClassA is not in the file path of the second project.
James

Yes, the second project can use a definition file .d.ts:
// ---------- projectA.d.ts ----------
declare module "projectA" {
export class A {
// ...
}
}
// ---------- ClassB.ts ----------
import projectA = require("projectA"); // Use the definition in projectA.d.ts
var a = new projectA.A();
See the section "Ambient External Modules" in the Handbook.
You can automatically generate a single definition file bundle from your projectA using dts-generator.

Following my comment that projectA was undefined when I did var a = new projectA.A(), I discovered that the reason for this lay in the way that the R.js optimized file (projectA.js) has been built - it needed an insertRequire added to the R.js build. This caused a require["projectA"] to be called when projectA was loaded and projectA was instantiated properly.
There are a quite a few moving parts here. It is a pity that typescript external modules and internal modules work so differently. Depending on the syntax declare module "SomeModuleName" and declare module SomeModuleName to distinguish via use of quotes between external and internal modules is confusing.
It would be great if the syntax was the same and the compiler -m flag handled all the underlying detail.

Related

How to export types in a TypeScript npm module

In TypeScript, say I want to have the user use my module's "internal" types so they can properly type their own variables when using my module - do I just export literally everything from my index.ts file to accomplish this?
// index.ts
export * from './file1' // uses types/interfaces defined in file1types
export * from './file2' // uses types/interfaces defined in file2types
export * from './types/file1types'
export * from './types/file2types'
Do .d.ts files help me accomplish this, or are they only for non-TS projects? Does tsconfig.json's option declaration: true help me accomplish this by generating a .d.ts for every TS file? Is this an alternative to exporting everything from a single index.ts file?
And if declaration: true does help me accomplish this, how would the user use all those generated .d.ts files within the build folder?
I would greatly appreciate some clarification as to how one typically exports types in TS projects. Thanks in advance.
For those who are like me, and have made sure declaration: true is set in your tsconfig.json, and that your build process correctly creates the corresponding .d.ts files to the appropriate directory pointed to by your package.json file, AND STILL somehow can't access the internal types of your module when testing on an external project -- try restarting the TS server in VSCode (assuming you're using VSCode)
So much time was wasted trying to figure this out, only to realize Typescript was functioning fine and I was being sabotaged by my IDE.
Without declaration files you can develop a package in TypeScript, compile it and expose it to other users as JavaScript code. Including them also allows TypeScript developers to use the package with any types you defined in it. They can get more type information whilst working with your library, such as required arguments types, function return types etc, as well as warnings from their IDE/Intellisense when there are conflicts.
The declaration: true in the file tsconfig.json instructs the TypeScript compiler to output declaration files (.d.ts). Often they are bundled in a single file e.g. index.d.ts and then a "types": path/to/index.d.ts field is added to the library's package.json file to inform TypeScript where to look for the types (when a user imports the package).

Haxe: how to keep unused class from being eliminated

I have classes that are never directly mentioned in other code, but only accessed using Type.resolveClass. I want them to be compiled and included in the app, but I can't get how to do this. I thought that #:keep (or #:keepSub) is exactly for this, but it does not work as I expected. This is what I do:
Main.hx:
package;
//import Foo; //uncomment this line to make it work
class Main {
static function main() trace(Type.resolveClass('Foo'));
}
Foo.hx:
package;
#:keep class Foo {}
But this traces null (I've tested JS and Flash)
Even if I compile with -dce no it still traces null.
Not sure if it's a compiler issue or I do not understand how it works.
This is not a compiler issue, it's correct behavior. If a module is never imported, it is never included in compilation to begin with. The compiler never gets to see the #:keep.
A common workaround for this is to use --macro include('package') (see Compiler.include()), which forces all modules in package to be compiled.
Note that a wildcard import (import package.*;) won't work, since wildcard imports are lazy:
When using wildcard imports on a package the compiler does not eagerly process all modules in that package. This means that these modules are never actually seen by the compiler unless used explicitly and are then not part of the generated output.
#:keep and #:keepSub only keep classes. In your case, Foo has never been included in the compilation so the compiler has nothing to keep.
You can list more than one entry point for your application in your hxml (or in your haxe ... command) to include some classes: haxe -cp src -main MainFoo Foo --interp will find Foo. (more on --interp here: http://old.haxe.org/doc/compiler#macro-options)
You can also include a package and all its classes with --macro include('my.package') but in your example your classes are on the root package and I don't know if you can include this one.
More info on include: http://api.haxe.org/haxe/macro/Compiler.html#include

How do I import a library into node without a Typescript/TSD definition?

I'm trying to use a session helper called connect-session-knex which is obscure enough that it does not have a published typescript definition. So when I try to compile my typescript node project, I get the error,
error TS2307 Cannot find module 'connect-session-knex'
Is there a way to ignore TS for this module only? How do I import it without the TSD? I know knex has a tsd, but the wrapper does not. I'm asking this from a generic standpoint of what to do with libraries without type definitions.
For anyone looking: Compiling typescript when it does not have tsd. Missing tsd. Without tsd.
error TS2307 Cannot find module 'connect-session-knex'
Is there a way to ignore TS for this module only? How do I import it without the TSD?
Use var/require instead of import/require. i.e.
var csk = require('connect-session-knex');
Note you should have node.d.ts included for require to be declared.
Also : https://basarat.gitbooks.io/typescript/content/docs/node/nodejs.html
Another suggestion is to start you own .d.ts file as an empty definition file and export the module. Then if you want to get intellisense on the module you can add definitions to it.
e.g. connect-session-knex.d.ts:
// declare module
declare module "connect-session-knex" {
}

TypeScript module namespacing while preserving multiple files after compile

I would like to take advantage of TypeScript's namespace/module features while preserving a multi-file output (each .ts file is compiled to a separate .js file.)
My desired organization and syntax is virtually the same as this QA: TypeScript module namespacing in multiple files.
However, rather than having TS compile all the files into one, I'm looking for a way to preserve the original file structure and have the compiler inject the necessary require() statements needed to make it work in Node.
e.g.
app.ts
/// <reference path="./model/animal.ts" />
var myAnimal = new MyNamespace.Model.Animal();
would compile to
app.js
var MyNamespace = { Model: { Animal: require('./model/animal') } };
var myAnimal = new MyNamespace.Model.Animal()
or similar
What steve said. Use external modules. Just fixing up the syntax:
import AnimalModel = require("./model/animal");
var myAnimal = new AnimalModel.Animal();
Basically same as var/require combo except that you use import to tell typescript to look for a .ts file and do its type inference.
Also to compile for Node use the --module commonjs module flag.
tsc --module commonjs app.ts
More : https://www.youtube.com/watch?v=KDrWLMUY0R0&hd=1
To take advantage of external modules (which were built for exactly this purpose), use the following:
import AnimalModel = "./model/animal.ts";
var myAnimal = new AnimalModel .Animal();
You don't need to use the module keyword in the animal.ts file.
You also need to pass the appropriate compiler module mode - for AMD (RequireJS) you pass --module amd...
tsc --module amd app.ts

Reference tag pollutes modules using Typescript

Let's say that I have file lib.ts which contains
/// <reference path="assets/webgl.d.ts" />
export var wrapper = 4;
Then I have file main.ts which contains
import lib = module("lib");
// when I hit space here, I see all the `webgl.d.ts` declarations
How can I stop webgl.d.ts polluting all the modules that load lib.ts? webgl.d.ts should be visible only inside of the lib.ts.
Although this isn't what you want to happen, this is actually how the TypeScript language is documented to work. From the TypeScript Language Specification:
Any files included as dependencies in turn have their references
analyzed in a transitive manner until all dependencies have been
determined.
So the TypeScript compiler is designed to walk the dependency tree for you.

Resources