5

Given these 2 typescript files

api/Token.ts

interface Token { 
    code: string
}
export default Token

and index.ts

export * from './api/Token'

tsc 1.5 with the --declarations switch will generate two .d.ts files (with similar content)

api/Token.d.ts

interface Token { 
    code: string;
}
export default Token;

and index.d.ts

export * from './api/Token';

Running grunt-dts-bundle with the following options

    dts_bundle: {
        release: {
            options: {
                name: 'my-module',
                main: 'index.d.ts'
            }
        }
    }

will generate an ambient module declaration file my-module.d.ts with the following content

declare module 'my-module' {
    export * from './api/Token';
}

However this declaration does not compile due to : Import or export declaration in an ambient module declaration cannot reference module through relative module name.

How can I automatically generate an ambient module declaration for the two typescript files above ?

EDIT

Please follow latest updates on https://github.com/Microsoft/TypeScript/issues/2262

Bruno Grieder
  • 28,128
  • 8
  • 69
  • 101

1 Answers1

3

I've recently written a blog post about this. To summarize, you can use autodts if you replace index.ts with api.ts, containing the following:

export {default as Token} from './api/Token';

Make sure api.ts is in the same place as the api directory (next to, not inside it).

Then you need a package.json file:

{
  "name": "api",
  "version": "1.0.0",
  "main": "dist/api.js",
  "scripts": {
    "preinstall": "npm install autodts",
    "postinstall": "autodts link",
    "prepublish": "tsc && autodts generate"
  },
  "typescript": {
    "definition": "index.d.ts"
  },
  "dependencies": {
    "autodts": "~0.0.4"
  },
  "devDependencies": {
    "@lib/autodts-generator": "~0.0.1",
    "typescript": "~1.5.3"
  }
}

It's important that the package name api matches the file api.ts and directory api. This way both Node.js and the TypeScript compiler will look in the same places when using your package.

Finally, you need a tsconfig.json file:

{
    "compilerOptions": {
        "declaration": true,
        "module": "CommonJS",
        "target": "es5",
        "outDir": "dist"
    },
    "files": [
        "api.ts"
    ]
}

Now npm install will compile your package and produce a bundled index.d.ts file as defined in the definition setting in package.json.

To use your package, you can do something like:

/// <reference path = "api/index.d.ts" />

import {Token} from 'api';

class foo {
    key: Token;
}

You can use autodts link to keep the reference path up to date, check the blog post and/or autodts docs for that.

The resulting index.d.ts contains:

/// <reference path="index.ref.d.ts" />
declare module 'api/Token' {
    interface Token {
        code: string;
    }
    export default Token;

}
declare module 'api' {
    export { default as Token } from 'api/Token';

}

index.ref.d.ts and api.js are blank.

jjrv
  • 4,211
  • 2
  • 40
  • 54
  • Thank you for detailed answer and my apologies for the late reply, I was waiting to test TypeScript 1.6 which completely changes the deal. Your solution is the way to go for TypeScript < 1.6. For TypeScript 1.6, there are some details in this GitHub issue: https://github.com/Microsoft/TypeScript/issues/247 – Bruno Grieder Sep 18 '15 at 13:46
  • @BrunoGrieder https://github.com/Microsoft/TypeScript/wiki/Typings-for-npm-packages is really unclear. I've been reading pages upon pages of comments on github issues but cannot find an answer to this really simple question. With typescript > 1.6, should you want to, for example, write a library that uses the "inversify" module (typed), and then you also want to use inversify outside the library. How do you achieve that?? – David Feb 29 '16 at 23:01
  • @David I never used inversify but you can find a boilerplate library [here](http://github.com/wadahiro/typescript-library-boilerplate) and some details I wrote [there](http://stackoverflow.com/questions/34221594/best-way-to-share-a-js-object-between-a-typescript-frontend-and-nodejs-backend/34225037#34225037) and somewhat similar near the bottom [there](http://stackoverflow.com/questions/35582275/using-an-external-typescript-library-within-a-typescript-internal-module/35588095#35588095) – Bruno Grieder Mar 01 '16 at 06:23