TypeScript icon indicating copy to clipboard operation
TypeScript copied to clipboard

What is the correct way to write a .d.ts file for a node module, which is referenced in package.json?

Open 0815fox opened this issue 8 years ago • 12 comments

So, i am working on a small module written in JS, but I want to make it easy to use that module in TypeScript as well. It adds a wrapper with some additional functionality around an existing JS module.

In my module path i have package.json with:

{
  "name": "parallel-nock",
  "version": "0.0.1",
  "description": "Adds a wrapper around nock, which allows to use it more efficiently in parallel tests.",
  "main": "index.js",
  "typings": "index.d.ts",
...
  "dependencies": {
    "bluebird": "^3.3.5",
    "nock": "^8.0.0"
  }
}

index.js is a very simple module, exporting just a function:

'use strict';
var Promise = require('bluebird');
var nock = require('nock');

var scopePromises = {};

function extendScope(Url) {
  return new Promise(function(resolve){
    scope = Object.create(nock(Url));
    scope.release = function() {
      resolve(scope);
    };
  };
}

function parallelNock(Url) {
  var scopePromise = scopePromises[Url];
  if (scopePromise) {
    scopePromise = scopePromise.then((Scope){
      return extendScope;
    });
  } else {
    scopePromise = extendScope(Url);
  }
  scopePromises[Url] = scopePromise;
}

module.exports = parallelNock;

And index.d.ts is:

declare module "parallel-nock" { 
  import nock = require('nock');

  namespace parallelNock {
    export function release():void;
  }

  function parallelNock (host: string, options?: any): any;
  export = parallelNock;
}
  • when I import that module into my project:
import parallelnock = require('parallel-nock');

, I get:

$ tsc
test.ts(4,31): error TS2656: Exported external package typings file '/home/mk/work/4.5.1/workspace2/cloud/node_modules/parallel-nock/index.d.ts' is not a module. Please contact the package author to update the package definition.
  • I found no "official" resource on how to write a correct .d.ts file, especially for a "module" which only exports a function.
  • I found [http://stackoverflow.com/questions/24029462/how-to-you-write-a-typescript-definition-file-for-a-node-module-that-exports-a-f](this on stackoverflow) but it seems not to work.
  • I oriented on the [https://github.com/DefinitelyTyped/DefinitelyTyped/blob/master/nock/nock.d.ts](typings file from the nock module I used) on DefinitelyTyped, which seems to do something very similar.
  • I am confused now.

0815fox avatar Apr 27 '16 12:04 0815fox

change your .d.ts file to be a module (i.e. a top level import or export), so it would look like:

import nock = require('nock');

declare namespace parallelNock {
    export function release():void;
}

declare function parallelNock (host: string, options?: any): any;
export = parallelNock;

mhegazy avatar Apr 27 '16 19:04 mhegazy

we have some documentation about exposing types in npm at: http://www.typescriptlang.org/docs/handbook/typings-for-npm-packages.html

that could definitely be better though. we are working on updating the typing acquisition story, so i will leave this issue open until that is done.

mhegazy avatar Apr 27 '16 19:04 mhegazy

for completeness, here is the guide for writing definition files: http://www.typescriptlang.org/docs/handbook/writing-declaration-files.html

mhegazy avatar Apr 27 '16 19:04 mhegazy

Oh, thank you for the valuable input, @mhegazy. Those guides did not help me to get the correct definition file. But I can follow you, so if I got it right, the folder containing the package.json becomes a module, when the .d.ts file, which typings in package.json points to, contains a top level import, which makes it an external module...

About documentation... well, I know, theres always not enough time... Anyway, what you already have is already very valuable.

0815fox avatar Apr 27 '16 19:04 0815fox

correct. and the name of the module that users import with is the name of the package. The logic should follow the same node package logic, i.e. index.d.ts would do, otherwise you need to specify "typings" entry, like you do with "main". so your package can look like

- parallelNock
| - package.json 
| - index.js
| - index.d.ts

or

- parallelNock
| - package.json  // "main": ".\lib\index.js", "typings" : ".\lib\index.d.ts"
| - lib
    | - index.js
    | - index.d.ts

mhegazy avatar Apr 27 '16 19:04 mhegazy

I did next:

  1. put index.d.ts for my package into <ProjectRoot>\typings\globals<PackageName>
  2. made update to <ProjectRoot>\typings\index.d.ts: /// <reference path="globals/<PackageName>/index.d.ts" /> and this helped to avoid TS2656 without using top level export. Is it correct way?

alexicum avatar Jun 28 '16 10:06 alexicum

In case you use typings, you should rather let it do that for you. You can use

typings install file:/path/to/file --save-dev

to add a dependency to a local type definition (refer to typings.json or index.d.ts) or you create a github-repository and fetch it from there.

0815fox avatar Jun 28 '16 11:06 0815fox

react markdown use in Typescript. error: TS2604: JSX element type 'Markdown' does not have any construct or call signatures

import * as Markdown from 'react-markdown';

<Markdown source={this.state.content} skipHtml={true} /> tsconfig.json:

{
  "compilerOptions": {
    "sourceMap": true,
    "module": "es6",
    "target": "es6",
    "lib": [
      "dom",
      "es7"
    ],
    "jsx": "preserve",
    "strict": true,
    "noImplicitAny": true,
    "moduleResolution": "node",
    "baseUrl": "src",
    "keyofStringsOnly": true,
    "allowSyntheticDefaultImports": true,
    "experimentalDecorators": true,
    "esModuleInterop": true,
    "typeRoots" : [
      "node_modules/@types/",
      "./typings/markdown.d.ts",
      "./typings/typings.d.ts"
    ]
  },
  "include": [
    "./src/**/*",
    "./typings/markdown.d.ts",
    "./typings/typings.d.ts"
  ],
  "exclude": [
    "node_modules",
    "dist"
  ]
}

markdown.d.ts:

declare function Markdown(props: any): any; export = Markdown;

Anyone konws how to resolve it? Thanks very much! i don not know why. @mhegazy

Yunnkii avatar Aug 03 '18 01:08 Yunnkii

use:

import Markdown from 'react-markdown';

mhegazy avatar Aug 03 '18 05:08 mhegazy

Thank you ,It doesn't report an error,but markdown file doesn't render . just render blank , not markdown file @mhegazy

Yunnkii avatar Aug 03 '18 05:08 Yunnkii

Trying to follow the tips given here, but not quite getting any traction. Thoughts?

https://stackoverflow.com/questions/57032253/providing-an-index-d-ts-file-for-canonical-json

oleersoy avatar Jul 15 '19 02:07 oleersoy

change your .d.ts file to be a module (i.e. a top level import or export), so it would look like:

import nock = require('nock');

declare namespace parallelNock {
    export function release():void;
}

declare function parallelNock (host: string, options?: any): any;
export = parallelNock;

Hi @mhegazy,

I am a noob programmer. I need to know how did you find this information or and link to the docs?

Any help is much appreciated.

dharnil avatar Feb 24 '24 11:02 dharnil