I have a quite large library written in Typescript 2.3.4 that is exporting a lot of ES6 modules and classes. I now need to use the library in an older browser app, written in typescript but using internal modules only. I managed to build a browser version of the library (thus polluting the global namespace) using rollup, and it works fine, at run time !
My problem now is to generate the typings (.d.ts) for the library when used as a global.
My code is compiled starting from a single index.ts file containing something like this:
import * as Promises from "./Promises";
export { Promises };
import * as CommonInterfaces from "./CommonInterfaces";
export { CommonInterfaces };
import * as Utils from "./Utils";
export { Utils };
import * as DomainEvents from "./DomainEvents";
export { DomainEvents };
...
I build the library in es6 modules and then use rollup to obtain a monolithic umd file that when loaded in a browser environment creates a single property called DDDTools in the "window" global, containing all of the modules exported, like this
window.DDDTools
+-- Promises
+-- CommonInterfaces
+-- Utils
+-- DomainEvents
+-- ...
this is exactly what I would obtain if I developed the library using internal modules (namespaces) instead of external modules.
Since the library is developed using external modules I can't use the d.ts files generated by the tsc compiler which are containing something like this (for the Utils module):
file: Utils/index.d.ts
export { ObjectIterator } from "./ObjectIterator";
export { SimpleGuid } from "./SimpleGuid";
export { SimpleIdentityMap } from "./SimpleIdentityMap";
taking the object iterator as an example
file: Utils/ObjectIterator.d.ts
export interface IObjectIteratorItem {
value: any;
propertyNameOrIndex: string;
parentObject: any;
}
export declare class ObjectIterator {
private srcObject;
private knownObjects;
private toBeTraversed;
private traversed;
private currentStackItem;
constructor(srcObject: any);
hasNext(): boolean;
getCurrent(): IObjectIteratorItem;
moveNext(): void;
reset(): void;
private isKnownObject(obj);
private addToKnownObjects(obj);
private addToStack(obj);
}
these .d.ts are fine if I use the library in my typescript sources as external modules, so I can write
/* fine, but make*/
import { ObjectIterator } from "DDDTools/Utils";
let oi = new ObjectIterator( ... // <-- and here my editor would show all the intellisense that makes typescript really cool ;)
BUT how do I say to typescript that exists a global whose name is DDDTools and that contains all the modules it exports ?
My first try was:
import * as dddtools from "DDDTools";
declare var DDDTools: dddtools;
but this makes my file an external module, and my poor browser app (containing a lot of files) is still namespace based (internal modules), doesn't compile anymore.
I think I need a way to create a .d.ts containing something like this
declare namespace DDDTools.Utils {
export interface IObjectIteratorItem {
value: any;
propertyNameOrIndex: string;
parentObject: any;
}
export declare class ObjectIterator {
private srcObject;
private knownObjects;
private toBeTraversed;
private traversed;
private currentStackItem;
constructor(srcObject: any);
hasNext(): boolean;
getCurrent(): IObjectIteratorItem;
moveNext(): void;
reset(): void;
private isKnownObject(obj);
private addToKnownObjects(obj);
private addToStack(obj);
}
}
Am I right ? If yes is out there a way to make it "automatically" ? I tried using tsc with the module option set to "system" (or amd) and outputting everything to a single file with the outFile option, but got something like this:
declare module "DDDTools/Utils/ObjectIterator" {
export interface IObjectIteratorItem {
value: any;
propertyNameOrIndex: string;
parentObject: any;
}
export class ObjectIterator {
private srcObject;
private knownObjects;
private toBeTraversed;
private traversed;
private currentStackItem;
constructor(srcObject: any);
hasNext(): boolean;
getCurrent(): IObjectIteratorItem;
moveNext(): void;
reset(): void;
private isKnownObject(obj);
private addToKnownObjects(obj);
private addToStack(obj);
}
}
... and so forth for each ES6 module I created
which is really really near to what I need, if only that declare module "DDDTools/Utils/ObjectIterator"
could become a declare namespace DDDTools.Utils.ObjectIterator
... but you know it isn't
Any help would be greatly appreciated!
What is the fastest way to generate a .d.ts file for a browser version of a library?
The fastest way is to just embrace the NPM ecosystem and let something like webpack do the bundling.
outFile is just pain that everyone can live without https://basarat.gitbooks.io/typescript/docs/tips/outFile.html so you will not find tooling that solves a broken code base. Better to fix the codebase instead of writing tooling to pile on to an unmaintainable system.