用 TypeScript 编写 npm 模块

我正在编写我的第一个 npm 模块。我以前曾经使用过 TypeScript,一个很大的问题是,对于许多模块来说,没有可用的定义文件。所以我认为用 TypeScript 编写我的模块是个好主意。

然而,我找不到任何关于这样做的最佳方法的信息。我发现了这个相关的问题“ 我可以用 CoffeeScript 编写 npm 包吗?”,人们建议只发布 JavaScript 文件。但与 CoffeeScript 文件相反,如果在 TypeScript 应用程序中使用 TypeScript 文件,那么它们实际上可能非常有用。

在发布 npm 模块时应该包含 TypeScript 文件,还是应该只发布 JavaScript 文件并提供生成的。将 d.ts 文件转换为 DefitelyType?

36811 次浏览

Here is a sample Node module written in TypeScript : https://github.com/basarat/ts-npm-module

Here is a sample TypeScript project that uses this sample module https://github.com/basarat/ts-npm-module-consume

Basically you need to :

  • compile with commonjs and declaration:true
  • generate a .d.ts file

And then

  • Have your ide read the generated .d.ts.

Atom-TypeScript just provides a nice workflow around this : https://github.com/TypeStrong/atom-typescript#packagejson-support

You can use autodts to handle distributing and using .d.ts files from npm also without support from the Atom IDE.

autodts generate will bundle all your own .d.ts files together for publishing on npm, and autodts link handles references to other installed packages, which may not always be directly under node_modules in a larger project split into several subpackages.

Both commands read their settings from package.json and tsconfig.json in "convention over configuration" style.

There's another answer on stackoverflow and a blog post with more details.

This is a more recent answer using TypeScript 1.8.10:

My project structure is:

|
|--- src
|--- test
|--- dist     <= My gulp file compiles and places the js, sourcemaps and .d.ts files here
|      |--- src
|      |--- test
|--- typings
.gitignore
.npmignore
gulpfile.js
package.json
README.md
tsconfig.json
tslint.json
typings.json

I added the following in .npmignore to avoid including extraneous files and keep the bare minimum to have the package imported and working:

node_modules/
*.log
*.tgz


src/
test/
gulpfile.js
tsconfig.json
tslint.json
typings.json
typings
dist/test

My .gitignore has:

typings


# ignore .js.map files
*.js.map
*.js
dist

My package.json has:

"main": "dist/src/index.js",
"typings":  "dist/src/index.d.ts",

Now I run: npm pack

The resultant file (when unzipped) has the following structure:

|
|--- dist
|       |--- src
|              |
|              index.js
|              index.js.map
|              index.d.ts
|
package.json
README.md

Now I go to the project where I want to use this as a library and type: npm install ./project-1.0.0.tgz

It successfully installs.

Now I create a file index.ts in my project where I just installed the npm import Project = require("project");

Typing Project. gives me the Intellisense options which was the point of this whole exercise.

Hope this helps someone else in using their TypeScript npm projects as internal libraries in their bigger projects.

PS: I believe that this approach of compiling projects to npm modules which can be used in other projects is reminiscent of the .dll in the .NET world. I could well imagine projects being organised in a Solution in VS Code where each project produces a an npm package which can then be used in another project in the solution as a dependency.

Since it took a fair amount of time for me to figure this out, I have posted it in case someone is stuck here.

I also posted it for a closed bug at: https://github.com/npm/npm/issues/11546


This example has been uploaded to Github: vchatterji/tsc-seed

You should publish the original typescript sources instead of the type definition. In package.json let the 'types' property point to the *.ts file.

*.d.ts are good to annotate existing JS libs, but as a consumer I'd rather read the typescript code than switching between type definitions and down-leveled, generated JS code.

I mainly follow the suggestion by Varun Chatterji

But, I would like to show a complete example with unit testing and code coverage and publishing it into npm and importing them using javascript or typescript

This module is written using typescript 2.2 and it is important to configure the prepublish hook to compile the code using tsc before publish it to npm

https://github.com/sweetim/haversine-position

https://www.npmjs.com/package/haversine-position

With TypeScript 4.x, TypeScript 3.x or TypeScript 2.x, the following steps describe what you have to do to create a library (npm package) with TypeScript:

  • Create your project as you normally would (with tests and everything)
  • Add declaration: true to tsconfig.json to generate typings.
  • Export the API through an index.ts
  • In the package.json, point to your generated typings. For example if your outDir is dist, then add "types": "dist/index.d.ts" to your package json.
  • In the package.json, point to your main entry file. For example if your outDir is dist and the main entry file is index.js, then add "main": "dist/index.js" to your package.json.
  • In the package.json, whitelist the files you'd like to ship to npm: files: ["/dist"]. An alternative approach is blacklisting with .npmignore, but it's harder to keep up to date.
  • Publish to npm with npm publish. Use semver specifications for updates (patch / bug fix npm version patch, non-breaking additions npm version minor, breaking api changes npm version major)

Since it got me a while to sift through all the outdated resources on this topic on the internet (like the one on this page...) I decided to wrap it up in how-to-write-a-typescript-library with an up-to-date working minimal example.