classinterfacetypescriptcommonjsambient

TypeScript 0.9.1 CommonJS: correctly declaring exported ambient class implementing external interface?


EDIT:

Put another way the following within a .d.ts file shouldn't produce compiler error TS2137 'Class "MyClass" does not implement interface "IInterface"':

interface IInterface {
    someMethod():void;
}
declare module "mod" {
    export class MyClass implements IInterface {
        constructor();
    }
}

because I'm not (and can't in a declaration) implementing anything. Is this a bug in the compiler or is there some other way/syntax to do what the above implies? I would think the compiler smart enough to know to precisely include IInterface's signature as part of MyClass, and not require its methods be redeclared.

ORIGINAL:

I'm trying to write a d.ts for the node component bunyan. Having a problem with exporting a class that implements an external interface, specifically RingBuffer which extends node's EventEmitter. The problem simplified is (below in a bunyan.d.ts file):

// this interface declared in <reference..., put inline here for simplicity
interface IExternal {
    inheritedMethod():void;
}

interface RingBuffer extends IExternal {
    write():void;
}
declare var RingBuffer: {
    new():RingBuffer;
}

declare module "bunyan" {
    export var RingBuffer;
}

then used in myNodeApp.js

/// <references path="bunyan.d.ts" />

import bunyan = require( 'bunyan' );
var rb = new bunyan.RingBuffer();

// compiler doesn't error on this; thinks RingBuffer is type any.
// also, no intellisense to show write() method.
rb.badFunc();

changing bunyan.d.ts to:

declare module "bunyan" {
    export class RingBuffer { constructor(); }
}

compiles, but same problem when used; no intellisense, no compile errors.


changing bunyan.d.ts to

declare module "bunyan" {
    export var RingBuffer:RingBuffer;
}

causes compile error in myNodeApp.js

// error TS2083: Invalid 'new' expression
import rb = new bunyan.RingBuffer();

removing from bunyan.d.ts

declare module "bunyan" {
    ...
}

causes compile error in myNodeApp.js

// error TS2071: Unable to resolve external module ''bunyan''
import bunyan = require( 'bunyan' );

changing bunyan.d.ts

interface IExternal {
    inheritedMethod():void;
}
interface IRingBuffer extends IExternal {
}

declare module "bunyan" {
    export class RingBuffer implements IRingBuffer {}
}

cause compile error

// error TS2137: Class "bunyan".RingBuffer declares interface IRingBuffer but 
// does not implement it: type '"bunyan".RingBuffer' is missing property
// 'inheritedMethod' from type 'IRingBuffer'

implying I have to redeclare all inherited methods from all extended interfaces, besides IRingBuffer, which seems a bit ridiculuous to have to do in a d.ts file

Does anyone know the 'correct' way to declare an ambient class that implements an interface for consumption in another CommonJS module??


Solution

  • An alternate way to define it would be the way Jquery's typescript definition is defined. You have separate interfaces for static and instance members. Here is a sample complete definition:

    interface IExternal {
        inheritedMethod():void;
    }
    
    interface IRingBuffer extends IExternal {
        write():void;
    }
    // Static functions and constructors 
    interface IRingBufferStatic{
        new():IRingBuffer;  
    }
    declare var RingBuffer:IRingBufferStatic;
    
    declare module "bunyan" {
        export var RingBuffer:IRingBufferStatic;
    }
    
    // In the second file 
    
    import bunyan = require( 'bunyan' );
    var rb = new bunyan.RingBuffer();
    
    // you get an error here 
    rb.badFunc();
    

    Try it online