typescripttsd

In TypeScript v2.2.2, how do you create a definition file for a Javascript library that doesn't have a tsd?


I am searching for a full example, or at least best practices for creating a definition file (doesn't necessarily have to be a tsd) for a JavaScript library that doesn't have one in @types or included with the package.

So far I've been able to put a basic solution together here, but it doesn't seem to follow the exact guidance given in the "Definitions" section on the TypeScript website.

In the repository above, I'm using the package @google-cloud/datastore, which from what I know doesn't have tsd file yet. The documentation is good enough that I should be able to create a manual definition file for the pieces I'm interested in, but I'm having a tough time figuring out what the best practice is for exporting definitions like this manually.

Specifically, from here, it says:

/*~ This is the module template file for class modules.
 *~ You should rename it to index.d.ts and place it in a folder with the same name as the module.
 *~ For example, if you were writing a file for "super-greeter", this
 *~ file should be 'super-greeter/index.d.ts'
 */

/*~ Note that ES6 modules cannot directly export class objects.
 *~ This file should be imported using the CommonJS-style:
 *~   import x = require('someLibrary');
 *~
 *~ Refer to the documentation to understand common
 *~ workarounds for this limitation of ES6 modules.
 */

/*~ If this module is a UMD module that exposes a global variable 'myClassLib' when
 *~ loaded outside a module loader environment, declare that global here.
 *~ Otherwise, delete this declaration.
 */

From the instructions above, it sounds like I should be able to drop an index.d.ts file into a folder outside of my node_modules/@types directory, that mimics the same folder structure as my module. For example, in my repository I have a top-level directory @google-cloud/datastore that contains an index.ts file, but from the documentation it sounds like I should be able to use an index.d.ts file; however, my modules, nor the compiler are able to find this. Do I need a compiler option for this?

Second, is the approach I've taken in the repository correct. This way is not documented on their website, and I had to guess at it before arriving at the solution. I'm essentially importing the JavaScript package google-cloud/datastore into the index.ts, adding my typings, and then exporting it to be used by my modules. However, my modules have to refer to the package by ./@google-cloud/datastore since this is the actual location of the TypeScript definitions.

In short, in TypeScript v2.2.2, what is the best practice for creating small, local, TypeScript definition files for JavaScript libraries that don't contain a tsd?

Aftermath

I updated my repository with a solution suggested by Alex, and everything seems to work as expected. I would like to note that it seemed to also work by just adding a { "baseUrl": "types" } parameter, but it wasn't clear to me why this would be correct so I went with the suggested approach. The --traceResolution flag is extremely helpful for this.

In this sample I made sure to also include another module with a TypeScript definition, lodash, to make sure that normal module resolution was still correct.

My directory/file structure:

+ js
  ...
+ node_modules
  + @google-cloud
    + datastore
  + lodash
  + @types
    + lodash
  + ...
+ types
  + @google-cloud
  - index.d.ts
  + datastore
    -  index.d.ts 
- index.ts
- package.json
- tsconfig.json

Trace Resolution

Just for the curious, I want to post an example of a incorrect/correct result from calling tsc --traceResolution. I've abbreviated the results for clarity.

Incorrect without the paths parameter TypeScript resolves @google-cloud/datastore to the index.js file, which is wrong.

======== Module name '@google-cloud/datastore' was successfully resolved to 'C:/Users/Kory/Documents/Repos/playground/manual-typescript-definition/node_modules/@google-cloud/datastore/src/index.js'. ========

Correct with the paths parameter. Notice that the @google-cloud/datastore resolves to the index.d.ts file and not the JavaScript file.

======== Module name '@google-cloud/datastore' was successfully resolved to 'C:/Users/Kory/Documents/Repos/playground/manual-typescript-definition/types/@google-cloud/datastore/index.d.ts'. ========

Solution

  • You can use compilerOptions paths and typeRoots to get tsc to detect custom .d.ts files. It will search the listed directories for folders matching your package (i.e. @google-cloud/datastore)

    For example

    "paths": {
      "*": [
        "types/*"
      ]
    },
    "typeRoots": [
      "./types"
    ]
    

    Where types is a folder at the root of your directory structure, and you create a file types/@google-cloud/datastore/index.d.ts

    You can use tsc --traceResolution as a quick way to see what files/folders tsc is considering while searching for type definitions