3

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!

2 Answers 2

5

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!

Sign up to request clarification or add additional context in comments.

2 Comments

actually -- this causes further headaches, as the tyranid library itself is structured around a default export for the main module.
Exactly. My assumption was that you didn't want to change your actual js library. Well ¯\_(ツ)_/¯
2

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 }

1 Comment

thanks for the help! It looks like I get the error "Module augmentation cannot introduce new names in the top level scope." when following that format though -- any ideas? example here: typescriptlang.org/play/…

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.