Ben Southgate
Ben Southgate

Reputation: 3798

Merge interface from namespace in module declaration file

I have a javascript library which has a type definition file here: https://github.com/tyranid-org/tyranid/blob/master/tyranid.d.ts which is exposed via the typings property in my package.json file.

a basic version of the definition file:

export default Tyr;

declare namespace Tyr {
  interface Document {
    $save(): Promise<Document>;
  }
}

I would like to extend the Document interface in a completely separate typescript library: https://github.com/CrossLead/tyranid-gracl which imports tyranid along with its typings, by adding a $newMethod() method to the document interface. Can this be done?

I've tried the following in a separate declaration file in the second repo, but it doesn't work:

import Tyr from 'tyranid';

declare namespace Tyr {

  interface Document {
    $newMethod(): number;
  }

}

I can modify both declarations if necessary -- its very possible I am not writing the original type definition file for tyranid correctly. Thanks!

Upvotes: 3

Views: 6852

Answers (2)

Pelle Jacobs
Pelle Jacobs

Reputation: 2579

You're trying to augment the module tyranid. The general syntax is pretty straightforward: here is an example of redux-thunk augmenting redux.

However, because tyranid exports default, module augmentation is not fully supported. export = has been fixed, as discussed in this issue.

To augment tyranid, the best I could come up with (inspired by this comment), is to throw the Tyr namespace into the global scope:

node_modules/tyranid/tyranid.d.ts

import * as Express from 'express';
import * as mongodb from 'mongodb';

export default TyrStatic;

declare global {
  namespace TyrStatic {
    // existing implementation of the Tyr namespace
  }
} 

./index.d.ts

declare namespace TyrStatic {
  interface specialInterface {
    someProp: number
  }
}

(depending on whether you need this augmentation to use external modules, you might need to wrap it in a declare global {})

src/app.ts

import Tyr from 'tyranid'
let specialVariable: Tyr.specialInterface = { someProp: 4 }

Upvotes: 2

Ben Southgate
Ben Southgate

Reputation: 3798

The following ended up working...

in node_modules/tyranid/tyranid.d.ts:

export = Tyr // must do "import * as Tyr from 'tyranid'" instead of default

declare namespace Tyr {
  export interface Document {
    // original definition...
  }
}

in mylib/tyranid-extensions.d.ts...

declare module "tyranid" {
  interface Document {
    addedMethod(): boolean; 
  }
}

Thanks @pelle-jacobs for the help!

Upvotes: 5

Related Questions