SammyJs: module and function impossible to define in 0.9?

Topics: General, Language Specification
May 21, 2013 at 3:18 PM
Edited May 21, 2013 at 3:22 PM
DefinitelyTyped has a definition for SammyJS that use modules to organize the definition. Sammy itself uses namespace Sammy for its objects, where you have Sammy.Object, Sammy.Application, Sammy.EventContext, etc, so the module mimics the behavior correctly.

Sammy is also a function, and the main way to call it is var app = Sammy(...);.

In 0.8, the definition works fine with the following (simplified) code:
module Sammy {
    export function (): Sammy.Application;
    ...
    export interface Application {
        new ();
        ...
    }
}
This code no longer compiles in 0.9 due to the breaking change "The ‘module’ keyword no longer creates a type", and requires the first function to be named in the module.

The issue is that I cannot find any code that produces the same behavior for this valid javascript code in TS 0.9.

Sammy is both a global function and a module for classes, and this is perfectly valid javascript. The definition should support a way to have all these lines compilling:
var app = Sammy();
var app = new Sammy.Application();
var app : Sammy.Application;
How to map this behavior in the definiton file for 0.9?
Developer
May 22, 2013 at 12:38 AM
The export assignment feature combined with merged declarations are designed to allow his sort of pattern going forward. It appears there is currently a bug blocking your particular case (we only just put these features in quite recently) but we do intend to support this pattern.
May 22, 2013 at 10:26 AM
Hi Dan,

Please correct me if I didn't understand this. Merged declarations would be declaring the same name twice, like this?
export module Sammy {
    interface Application { }
}
export interface SammyStatic { }
declare var Sammy : SammyStatic; 
If not, can you give an example on what should it look like in 0.9?
May 22, 2013 at 5:28 PM
What you're looking for is the following:
function Sammy() { return null; }

module Sammy {
    export class Application {
        constructor() { }
    }
}



export = Sammy;
But as Dan said, that's currently blocked by a bug on the import side.
May 22, 2013 at 11:48 PM
How would one declare such a module with the new syntax. E.g what is the new syntax for the declaration:
declare module Sammy {
    export function (): any;   
}
May 23, 2013 at 8:45 AM
Edited May 23, 2013 at 8:46 AM
@basarat's question is also mine. Basically, we need new syntax for these two:
declare module Sammy {
    export class SammyClass {
        constructor();
    }
    export function (): any;
    export function new (): SammyClass;
}
May 23, 2013 at 9:33 AM
Incidentally, just noticed the ID of this discussion -- 444444.

In Chinese, the number 4 is bad luck, since it sounds similar to "death".

Hope this won't affect this extremely important feature...
May 23, 2013 at 10:23 AM
I did some tests last night and it seems to work, and it even compiles and produces the expected code in . For basarat and schungx, here is what I did:

Get Paul's code and compile with --declaration

Sammy.ts:
function Sammy() { return null; }

module Sammy {
    export class Application {
        constructor() { }
    }
}
--
tsc --declaration Sammy.ts
The declaration generated in Sammy.d.ts for this is:
declare function Sammy();
declare module Sammy {
    class Application {
        constructor();
    }
}
Create a "file.ts" and reference the Sammy.d.ts you just created:
/// <reference path="Sammy.d.ts" />

var a = Sammy();
var b: Sammy.Application;
var c = new Sammy.Application();
Seems to work for both the declaration as for real javascript code. Overloads can be declared as usual.


So Paul/Dan, it seems that if I'm not using modules and the import clause, this should be possible to map today.
May 23, 2013 at 11:54 PM
Yup nvivo. However (as you stated at the end) it will not work when using modules and the import clause. i.e. the following is invalid:
declare function "mymodule"();
declare module "mymodule"{
    
}

import x = module("mymodule");
x(); 
May 23, 2013 at 11:57 PM
So the question is how can we declare the following in the new syntax:
declare module "mymodule" {
    export function (): any;   
}
May 26, 2013 at 5:51 AM
Thought I'd post it here. The planned declare syntax:
declare module 'express' {
    function someName() : number;

    export = someName;
}
Source: https://typescript.codeplex.com/workitem/1058
May 28, 2013 at 12:30 AM
I still don't get it how to fix Express definitions:
interface ExpressApplication {
    ...
}

interface Express extends ExpressApplication {
    ...
    (): ExpressApplication;
    ...
}

declare module "express" {
    export function (): Express;
    export function bodyParser(options?: any): Handler;
    ...
With what do I have to replace this line: export function (): Express;
May 28, 2013 at 12:34 AM
@jzvelc here you go:
interface ExpressApplication {
    ...
}

interface Express extends ExpressApplication {
    ...
    (): ExpressApplication;
    ...
}
declare module "express" {
   export function moduleExport(): Express;
   export function bodyParser(options?: any): Handler;
   ...
   export = moduleExport;
}
May 28, 2013 at 1:02 AM
Edited May 28, 2013 at 1:04 AM
I actually tried this but it doesn't work.
I get TS1064 Export assignment not allowed in module with exported element in line:
export = moduleExport;
Problem is that if I remove export before function they don't get exported =)
May 28, 2013 at 1:06 AM
It will not work with the released 0.9.0-alpha version. You need to use the latest src version from https://typescript.codeplex.com/SourceControl/latest

The compiled code is in the bin folder.
May 28, 2013 at 10:14 AM
I am using release-0.9.0 branch and not release-0.9.0-alpha.
I did fresh clone as demonstrated in blog:
git clone https://git01.codeplex.com/typescript
cd typescript
git checkout release-0.9.0

Am I missing something? I use tsc.js from bin folder.
@basarat does your code for express compile?
May 29, 2013 at 11:07 AM
I have also tried with develop branch and it doesn't work either ...
I can't get around TS1064 Export assignment not allowed in module with exported element error ...
Does anybody have solution to this because I would like to make transition to 0.9.0?
I have tried with branches: develop, release-0.9.0-alpha, release-0.9.0 ...
Developer
May 29, 2013 at 10:58 PM
This is not a bug. You cannot use export assignment (ie export = ) in a module that also uses the export keyword on other elements. You must use one or the other. If you only want to export the moduleExport function, then just export it the same way you always did pre-0.9.0. If you have multiple declarations named moduleExport which you want to merge and export, then use 'export = moduleExport.' If you want to export a merged declaration along with other things, you will need to compose some modules and interfaces which describe the shape of the thing you want to export=.
May 29, 2013 at 11:08 PM
Well I would somehow like to achieve to use Express as I did before:
import express = require("express"); // I guess this is the new syntax in 0.9.0 instead of module
var app = express();
Current definition file for express is broken due to module no longer exports a type ...
declare module "express" {
    export function (): Express; // This is the problamatic part
    export function bodyParser(options?: any): Handler;
    ...
How could I simulate the problematic line in 0.9.0?
May 29, 2013 at 11:51 PM
@danquirk the issue with what jzvelc wants to do is that express is defined inside a string i.e. "express" because that is the format it needs to be in to be usable by module("express")

However because of this he cannot get access to this variable "express" elsewhere as quotes are not allowed in variable names. Therefore he cannot use it to shape an object for the the single export =.

So I don't see a new syntax for what jzvelc wants.
Developer
May 30, 2013 at 12:39 AM
@jzvelc

I see the confusion. I could've been more explicit in what I meant at the end of my last reply about using modules and interfaces to describe the shape of the exports along with an export =. This is the simplest example of what you want. An external module 'express' which is imported and then can be used as if it has a call signature:
declare module 'express' {
    function foo(): string;
    export = foo;
}

import express = require('express');
var r = express(); // r is string
If you wanted to export more than just that individual function, then you could instead have the right hand side of the export= statement be an interface name. This interface would effectively be describing the shape of your 'express' module. So it would include a call signature and potentially other things. For example,
declare module 'express' {
    interface I {
        (): string; // this call signature is performing the same role as 'foo' in the first example
        doStuff(x: number): void;
    }
    export = I;
}

import express = require('express');
var r = express(); // r is string
express.doStuff(3);
There is currently a bug blocking this example from working today but that is the pattern that captures the expressions you want. You can then combine this with merged declarations to export an identifier that is multiple things (ex a module named 'foo' and a function named 'foo') or an interface describing the shape of those things. Is that clearer?
May 30, 2013 at 9:34 AM
Thank you for your explanation. So you are saying that one declaration file may export more stuff this way (multiple export = ? expressions)?
Although this is clear now I guess I should wait until this is fixed.

I have another question and maybe it should go in another post but I think it is related ...
Consider this example
interface Test {
    ...
}
class Tester {
    constructor() {
        console.log("Class constructed.");
    }
    public dotest(t: Test): void {
        console.log("Index");
    }
}
export = Tester;
I get following error when I compile this:
TS 2038 Parameter t of public method from exported class has or is using private type Test

Similar happens when I try to access interfaces which are outside of current namespace. This is logical but how can I refer to things which are in different namespace (global or another module)?
outside of current namespace or perhaps are in global namespace?
May 30, 2013 at 4:05 PM
Dan, here is another issue related to the module not being a type anymore.
How to declare "noConflict" and similar methods?

0.8 allowed for this:
declare module Backbone {
    class View { }
    function noConflict(): Backbone;
}

var bb = Backbone.noConflict();
On latest LKG, we get:

error TS4022: Type reference cannot refer to container 'Backbone'.

Following the guidelines, the alternative would be:
declare module Backbone {
    class View {}
}
declare class Backbone {
    static noConflict(): Backbone;
}

var bb = Backbone.noConflict();
But this gives the following error:

test.ts(8,19): error TS2094: The property 'noConflict' does not exist on value of type 'Backbone'.


A similar issue happens when defining aliases for modules.
declare module Sammy {
    class View {}
}
interface JQueryStatic {
    sammy: Sammy;
}
This gives an error TS4022: Type reference cannot refer to container 'Sammy'.

Again, following the guideline to multiple declarations, this seem this works:
declare module Sammy {
    class View {}
}
declare class Sammy {
}
interface JQueryStatic {
    sammy: Sammy;
}
Now, it seems very strange that we must declare this empty class to create the alias.

I was wondering: why is this rule of 'modules cannot be used as types' being enforced? Is this enforced by ES6 as well?
It seems that sometimes it would be useful to make containers behave as types, as the case above.
Developer
May 30, 2013 at 7:28 PM
Sorry, I got confused with my last reply as the design has evolved. The bug I was referring to I believe is actually the current design, you can use the imported name in a type position if it makes sense to given the export=. So the original Express example looks like this:
declare module 'express' {
    interface I {
        (): string; // this call signature is performing the same role as 'foo' in the first example
        doStuff(x: number): void;
    }
    export = I;
}

import express = require('express');
var r = express(); // error
express.doStuff(3); // error
var e: express; // express is an interface type, not a module, so this is allowed
var r2 = e(); // r2 is string
e.doStuff(1);
For your second example, this works:
module M {
    export interface Test {
        x: number;
    }
    export class Tester {
        constructor() { }
        public dotest(t: Test): void { }
    }
}
export = M;
import e = require('testers');
var test: e.Test;
var tester: e.Tester;
tester.dotest(1); // error
tester.dotest(test); // works
For your Backbone example there is a bug there blocking that. You should be able to merge a class and module of the same name as long as the class definition comes first or is ambient.

I'll have to go back and look through the design notes to give you the canonical explanation for why the modules as types situation is how it is today. Someone else may chime in first.
May 30, 2013 at 9:13 PM
Edited May 30, 2013 at 11:25 PM
In your express example is this the planned design for exporting? Well it is not intuitive to users that came from javascript ...
There should be a way to just write (the same way as in javascript):
import express = require('express');
var app = express(); // express should already be an express interface type
Approach you have shown is confusing because this is not how express works (many definition files for different modules will export stuff in many different ways):
import express = require("express");
var e: express; // user won't know what to do here unless he figures it out from definition file, besides this will present way too many variables and it is unreadable
var app = e();
In line var e: express what is express referring to? You said "express" is an interface type but it is a module name which doesn't export a type anymore? Shouldn't it be:
var e: Express;
because "Express" is an interface ... It works with both, is that intended? I suggest you include a sample in sample folder which shows how to correctly use this pattern and distribute it with typescript release (such as express 2, node.js, imageboard, ...)

For the second example with tester I know this approach, but I would like to somehow export it in the way that module.exports works.
So basically I need to export a class (like module.exports in javascript) and other stuff with normal (exports.somefunction = x in javascript) so I could do:
import e = require('testers');
var tester = new e(); // class is exported directly
var somedata = e.getDataFunction(); // getDataFunction is outside Tester class
Well this is not as critical as the first example as long as it is possible to write definition files for existing javascript modules that have this pattern.

As I can see the current state of typescript allows us to write typescript files which resemble module.exports but it is impossible to write such definition files for existing modules (without using extra variable to define the type).

Edit:
This seems to work:
/// <reference path="express.d.ts" />
import express = require("express");
var app = (<express>express)();
But this is still confusing because many people who write definition files will follow different conventions and thus <type> will vary ... Besides this way I have to provide the reference to express definition in every file (normally I provide definition file in root of the project which is resolved automatically and I don't reference it explicitly where I don't use type casting).
Developer
May 31, 2013 at 12:44 AM
There should be a way to just write (the same way as in javascript):
import express = require('express');
var app = express(); // express should already be an express interface type
The problem is you're doing something that isn't the same as JavaScript. In JavaScript when you import a name it always represents something with a value. There is no concept of importing a name which is only a type definition, or a container of type definitions, or a container of type definitions and values. The name 'express' introduced by the import is of a type that depends on the value of the export assignment in the target module. It is not necessarily a module, this is part of why we now use the require keyword rather than the module keyword as in the older versions of Typescript. So in this case the name introduced by import is an interface. You would not expect this to work:
interface I {
    (): string; 
    doStuff(x: number): void;
}
var r = I();
and that is basically what you have now, the name is just express instead of I as it was in the original module.
import express = require("express");
var e: express; // user won't know what to do here unless he figures it out from definition file, besides this will present way too many variables and it is unreadable
var app = e();
How is this different from a regular interface? If I wrote this along with my last code snippet:
var r2: I;
you would have the same issue would you not? You can mouse over the type annotation to see more information for the type (like the fact that it is an interface), use Go To Definition on the type symbol (it even takes you to the interface that was the target of the export= in the imported module), or dot off the identifier of that type to see what members it provides. I'm not sure what 'too many variables' means as I see a completion list which properly displays the fact that express is a callable function (apply/arguments/bind/etc) with an additional member named doStuff.
In line var e: express what is express referring to? You said "express" is an interface type but it is a module name which doesn't export a type anymore? Shouldn't it be:
var e: Express;
because "Express" is an interface ... It works with both, is that intended?
To be clearer, let's use this line as the example so there's no confusion about names:
import x = require("express");
x is an interface type because the module named 'express' which is being imported has an export assignment whose value is an interface. If the 'express' module's export assignment statement were a different type, then you would need to use it differently at the import site. For example:
declare module 'express' {
    module M {
        export interface I {
            (): string; // this call signature is performing the same role as 'foo' in the first example
            doStuff(x: number): void;
        }
    }
    export = M;
}

import x = require('express');
var e: x; // x is a module, so this is an error
var e2: x.I; // works
var r2 = e2(); // r2 is string
Does that make sense? I think you're noticed this in the Tester example where a class is the target of the export assignment so now the imported name is a class that can be new'd up.
I suggest you include a sample in sample folder which shows how to correctly use this pattern > and distribute it with typescript release (such as express 2, node.js, imageboard, ...)
We absolutely intend to have some samples and documentation for all the new stuff as time goes on. We're busy getting the features working, then we'll make sure to have documentation to go along with an official, non-preview release :)
This seems to work:
I don't think this does what you think it does. The type assertion should actually be an error because there is no type express to cast to. Even if it were somehow valid at compile time, you've cast the express.I interface to the type of the module express. At runtime this will fail because your object is not actually a callable function type.
May 31, 2013 at 9:02 AM
Edited May 31, 2013 at 10:20 AM
Thanks for all your answers, things are becoming clearer now.

This example compiles ok and works even at runtime (I don't see why this is a problem if I reference the definition file):
/// <reference path="express.d.ts" />
import express = require("express");
var app = (<express>express)(); //
app.get('/hello.txt', function(req, res){
    res.send('Hello World');
});
app.listen(3000);
On the other hand it is weird to cast interface to interface (I get your point, we need another variable of type express).
But your example fails at runtime with TypeError undefined is not a function:
/// <reference path="../node.d.ts" />
/// <reference path="../express.d.ts" />
import express = require("express");
export function main(args: string[]): number {
    var e: express;
    var app = e();
    app.use(e.static(__dirname + '/lib'));
    app.get('/hello.txt', function(req, res){
        res.send('Hello World');
    });
    app.listen(3000);
}
Resulting javascript:
var express = require("express");
function main(argc, args) {
    var e;
    var app = (express)();
    app.use(e.static(__dirname + '/lib'));
    app.get('/hello.txt', function (req, res) {
        res.send('Hello World');
    });
    app.listen(3000);

    return -1;
}
exports.main = main;
Is that the bug you were talking about?
My current definition is as follows:
declare module "express" {
    interface Wrapper {
        (): Express;
        static(root: string, options?: any): Handler;
        ...
    }
    export = Wrapper;
}
So exported type is of type Wrapper interface:
var e: express; // express is Wrapper?
And when we call the constructor of e it becomes Express. Is that correct?

If I understand with this snippet of code we lost all methods of Wrapper interface:
/// <reference path="express.d.ts" />
import express = require("express");
var app = (<Express>express)(); // note that Express is capitalized
app.get('/hello.txt', function(req, res){
    res.send('Hello World');
});
app.listen(3000);
With too many variables I meant that the code will become less readable because developers expect to call:
var app = express();
With current approach we have to define another var with another name. For example let us import 5 modules:
import express = require("express");
import socket = require("socket.io");
...
var e: express;
var s: socket;
...
We will have twice as many variables only for modules and the source code will become unclean.

I hope you understand what is bothering me (things that shouldn't work work and things that should don't). I still think that code in 0.8.3 was much cleaner:
import express = require("express"):
var app = express();
Jul 3, 2013 at 1:13 AM
Edited Jul 3, 2013 at 1:14 AM
Just to tag on here....this is needed for a lot of Node modules and many js libs which define optional AMD versions....jQuery is a big example of a library that appears to be broken for AMD as a result of these issues.
Jul 3, 2013 at 5:32 AM
Edited Jul 3, 2013 at 5:33 AM
Here's how I offered both standard library support and AMD/CommonJS support for Q: https://github.com/borisyankov/DefinitelyTyped/blob/master/q/Q.d.ts#L87
Jul 5, 2013 at 1:54 PM
Edited Jul 5, 2013 at 3:30 PM
I just wasted an hour wrestling with trying to fix sammy.d.ts also - so what's the end result? Is it possible to model in typescript or not? <s>I gave up</s>.. the new module syntax is even more obtuse than before.

Anyone?

Edit: I figured it out using the merged declaration trick (but I have some comments on this, see below)
interface SammyFunc {
    (): Sammy.Application;
    (selector: string): Sammy.Application;
    (handler: Function): Sammy.Application;
    (selector: string, handler: Function): Sammy.Application;
}

// NOTE: This should work, but doesn't - we get a name conflict. 
// If it did work, we could avoid the duplicate declarations for interface and functions
//declare var Sammy: SammyFunc;

declare function Sammy(): Sammy.Application;
declare function Sammy(selector: string): Sammy.Application;
declare function Sammy(handler: Function): Sammy.Application;
declare function Sammy(selector: string, handler: Function): Sammy.Application;

interface JQueryStatic {
    sammy: SammyFunc;
}

declare module Sammy {
    //export function (): Sammy.Application;
    //export function (selector: string): Sammy.Application;
    //export function (handler: Function): Sammy.Application;
    //export function (selector: string, handler: Function): Sammy.Application;

    export function Cache(app, options);
    export function DataCacheProxy(initial, $element);
    export function DataLocationProxy(app, data_name, href_attribute);
    export function DefaultLocationProxy(app, run_interval_every);
    export function EJS(app, method_alias);
    ...
Everything in the module remains unchanged apart from the four commented out unnamed functions which are replaced by the interface SammyFunc.
Jul 5, 2013 at 4:29 PM
Edited Jul 5, 2013 at 6:03 PM
FYI: I submitted a pull request to Boris for definitelytyped, and it was accepted about an hour ago. I expect it will make the next nuget push.
Jul 5, 2013 at 5:42 PM
I'm not familiar with Sammy, but are you trying to model the following calls?


var app: Sammy.Application;
var app = Sammy();
var app = new Sammy.Application();

var app = $.sammy();

and for Cache?

Sammy.Cache(app, ......)?
Jul 5, 2013 at 6:02 PM
Hey Paul, yes, that's it - I used the merge trick as shown further up the thread and came to the solution above.
Aug 1, 2013 at 6:48 PM
It's really hard to describe just how frustrated I am right now. I read this thread almost a month ago. I've come back to it today and it is still not clear how to accomplish this. I will spell out my scenario. Please, would someone show how to create the declaration file?

I have a module named 'durandal/events'.
The module works as a constructor function, so I should be able to do this:
import Events = module('durandal/events');

var publisher = new Events();
publisher.on('some:event', callback);
The module also has a function to allow it to be used as a mixin. So, I should be able to do this:
import Events = module('durandal/events');

var something = {};
Events.includeIn(something);
I have messed around with so many combinations in my definition file...and have not found anything that works. I would really appreciate some assistance. My community is begging for an official TypeScript definition file for my 2.0 release and I told them I would have one. Right now, it looks like there are portions of my library which are not possible to describe. Please, please, prove me wrong.
Aug 1, 2013 at 7:10 PM
Ok. I did manage to find a way to get this working. BUT...I get a red squigly from VS on my export = Events, where Events is a declared class. Also, I get no intellisense at all on the module from my TypeScript code. It does compile correctly though. So, I guess I can live with that for now. I'm eager awaiting a release that fixes these issues...and hopefully improves the speed of intellisense...which is so slow it's pretty much useless at this point.
Aug 1, 2013 at 7:20 PM
Edited Aug 1, 2013 at 7:21 PM
And the really strange thing is....if I hover my mouse over any of the class defined members in my TypeScript code, a tooltip pops up displaying the correct metadata and doc comment values. But, if I 'dot' off the object itself, no member completion list comes up.

Here's my code for reference:
interface EventSubscription {
    then(thenCallback: Function, context?: any): EventSubscription;
    on(thenCallback: Function, context?: any): EventSubscription;
    off(): EventSubscription;
}

declare class Events {
    constructor();
    on(events: string): EventSubscription; 
    on(events: string, callback: Function, context?: any): Events;
    off(events: string, callback: Function, context?: any): Events;
    trigger(events: string, ...eventArgs:any[]): Events;
    proxy(events: string): Function;
    static includeIn(targetObject: any): void;
}

declare module 'durandal/events' {
    export = Events;
}
And I use it like this:
import Events = module('durandal/events');

var ev = new Events();
    
ev.on('test:event').then(arg => {
    console.log(arg);
});

ev.trigger('test:event', { prop: 'value' });

Events.includeIn({});
This does compile to the correct JavaScript code. If I hover over the function calls, I get tooltips with the correct metadata. But, I get no member completion. Is this just a bug in the VS tooling?
Aug 2, 2013 at 8:33 PM
I would like to point out that the solution above is not ideal in another way: both the class and the interface are in global scope. They really should not be, but I could not find a way to include them inside the module. As always, any help is appreciated.
Developer
Aug 2, 2013 at 11:13 PM
The following works:
interface EventSubscription {
    then(thenCallback: Function, context?: any): EventSubscription;
    on(thenCallback: Function, context?: any): EventSubscription;
    off(): EventSubscription;
}

declare module "durandal/events" {
    class Events {
        constructor();
        on(events: string): EventSubscription;
        on(events: string, callback: Function, context?: any): Events;
        off(events: string, callback: Function, context?: any): Events;
        trigger(events: string, ...eventArgs: any[]): Events;
        proxy(events: string): Function;
        static includeIn(targetObject: any): void;
    }
    export = Events;
}
You could also move the interface inside the external module:
declare module "durandal/events" {
    class Events {
        constructor();
        on(events: string): Events.EventSubscription;
        on(events: string, callback: Function, context?: any): Events;
        off(events: string, callback: Function, context?: any): Events;
        trigger(events: string, ...eventArgs: any[]): Events;
        proxy(events: string): Function;
    }
    module Events {
        export interface EventSubscription {
            then(thenCallback: Function, context?: any): EventSubscription;
            on(thenCallback: Function, context?: any): EventSubscription;
            off(): EventSubscription;
        }
        export function includeIn(targetObject: any): void;
    }
    export = Events;
}
In 0.9 we merge class and module declarations for the same name. Basically the module becomes an alternate (and more complete) way of declaring the static side of the class. I've moved the declaration of the 'includeIn' method into the module to illustrate this. Either way of declaring it works.

Unfortunately, there are still some bugs in the class/module merging parts of the compiler. Specifically, it is not possible to refer to interfaces declared in the merged class/module by name:
/// <reference path="durandal.d.ts"/>

import Events = require('durandal/events');
var x: Events.EventSubscription;  // Should not be an error
We're fixing this, and other than the inability to reference the interface by name things should work. Still, until it is fixed you might want to go with the first solution.
Aug 3, 2013 at 1:05 AM
Fantastic. Thank you very much. This example, particularly the second one, sheds a lot of light on things for me. I had used some merging in another one of my modules, but hadn't thought of this particular combination. The second example will work perfectly to describe my API. Unfortunately, the bug you mention does mean I cannot use it at this time as I have other module definitions which need to reference the interface. So, I ended up going with your first option for now. That will work well enough until the compiler issues are resolved. I should also mention that intellisense doesn't work with this combination. Not a biggie, but wanted to mention that for completeness.

Again, thank you. My community is going to be very excited about us delivering an official TypeScript definition file in our next release. I think this was the last piece of information I needed to complete it.
Aug 22, 2013 at 7:12 AM
Your answer made things much clearer. However, how can you export a generic class from a module? I'd think something like this should work:
declare module 'someModule' {
    module someModule {
        interface GenClass<T> {
            prop:T;
        }
        interface GenClassStatic<T> {
            ():GenClass<T>;
        }
    }

    // this wont work :(, since we need a type for the generic arg;
    // var someModule:GenClassStatic<???>;

    export = GenClassStatic;
}
some other file:
import someModule = require('someModule');
// compile error TS2088: Cannot invoke an expression whose type lacks a call signature
var x = someModule<string>();
Is there a way to declare module "someModule" that is a generic class?