Escribir módulos de NPM en TypeScript

103

Estoy trabajando en mi primer módulo de NPM. Trabajé brevemente con mecanografiado antes y un gran problema fue que para muchos módulos no había archivos de definición disponibles. Así que pensé que sería una buena idea escribir mi módulo a máquina.

Sin embargo, no puedo encontrar ninguna información sobre la mejor manera de hacerlo. Encontré esta pregunta relacionada " ¿Puedo escribir el paquete npm en coffeescript? " Donde la gente sugiere publicar solo los archivos javascript. Pero a diferencia de los archivos coffeescript, los archivos mecanografiados pueden ser útiles si se utilizan dentro de una aplicación mecanografiada.

¿Debo incluir archivos de Typecript al publicar un módulo NPM, o debo publicar solo los archivos javascript y proporcionar los archivos .d.ts generados a DefinitelyTyped?

Andreas Gassmann
fuente
2
Notas útiles: escribí el proyecto, copee , junto con una publicación de blog para guiarlo a través de la configuración de un proyecto de TS para emitir definiciones de tipo junto con los objetivos de CJS y ESM antes de publicar en npm. Esto maximizará el uso con node.js y los navegadores en el futuro.
Styfle

Respuestas:

84

Aquí hay un módulo de nodo de muestra escrito en TypeScript: https://github.com/basarat/ts-npm-module

Aquí hay un proyecto de TypeScript de muestra que usa este módulo de muestra https://github.com/basarat/ts-npm-module-consume

Básicamente necesitas:

  • compilar con commonjsydeclaration:true
  • generar un .d.tsarchivo

Y entonces

  • Haga que su ide lea el archivo .d.ts.

Atom-TypeScript solo proporciona un buen flujo de trabajo en torno a esto: https://github.com/TypeStrong/atom-typescript#packagejson-support

basarat
fuente
Es necesario actualizar el enlace de ancla de Atom-TypeScript (el ancla ya no es válida).
Fidan Hakaj
@basarat, en ts-npm-module estás usando "version": "1.5.0-alpha". Supongo que esta es la versión de Typecript con la que estás transpilando. ¿Importa dejar esto fuera? (no lo hace automáticamente el complemento Atom). Si se usa una versión, ¿será necesario que otros usuarios usen la versión exacta para transpilar (o solo las más nuevas)? (¿O tal vez es la versión de tsconfig.json?)
justin
¿Tiene algún caso de uso con módulos que dependan de otras bibliotecas? Para evitar el problema de la definición duplicada, debe configurar tsconfig.json, pero esto parece demasiado manual en mi opinión.
Sérgio Michels
1
¿Seguiría defendiendo este enfoque en el cuarto trimestre de 2016?
SuperUberDuper
7
Este fue un buen instructivo
chrismarx
78

Con TypeScript 3.xo TypeScript 2.x, los siguientes pasos describen lo que debe hacer para crear una biblioteca (paquete npm) con TypeScript:

  • Crea tu proyecto como lo harías normalmente (con pruebas y todo)
  • Agregue declaration: truea tsconfig.jsonpara generar mecanografía.
  • Exportar la API a través de un index.ts
  • En package.json, apunte a sus mecanografiados generados. Por ejemplo, si lo outDires dist, agréguelo "types": "dist/index.d.ts"a su paquete json.
  • En package.json, apunte a su archivo de entrada principal. Por ejemplo, si tu outDires disty el archivo de entrada principal es index.js, agrégalo "main": "dist/index.js"a tu package.json.
  • Cree un .npmignorepara ignorar archivos innecesarios (por ejemplo, la fuente).
  • Publicar en npm con npm publish. Utilice las especificaciones de semver para las actualizaciones (parche / corrección de errores npm version patch, adiciones npm version minorpermanentes, cambios de API importantes npm version major)

Como me tomó un tiempo examinar todos los recursos desactualizados sobre este tema en Internet (como el de esta página ...), decidí resumirlo en cómo-escribir-una-biblioteca-mecanografiada con un ejemplo mínimo de trabajo actualizado.

bersling
fuente
¿Tendré que registrar js en el control de código fuente? ¿O npm mantiene su propia versión del código?
Olian04
1
@ Olian04 Le dices a crear un .npmignorearchivo para decirle a npm qué archivos ignorar al publicar (los .tsarchivos) y .gitignorea decirle a git qué archivos ignorar ( dist/)
Purag
@ Olian04 no, no es necesario (y IMO no debería) confirmar los archivos JS generados. Esos no son parte de la fuente del proyecto.
Josh M.
59

Esta es una respuesta más reciente usando TypeScript 1.8.10:

La estructura de mi proyecto es:

|
|--- 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

Agregué lo siguiente .npmignorepara evitar incluir archivos extraños y mantener lo mínimo para que el paquete se importe y funcione:

node_modules/
*.log
*.tgz

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

Mi .gitignoretiene:

typings

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

Mi package.jsontiene:

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

Ahora corro: npm pack

El archivo resultante (cuando se descomprime) tiene la siguiente estructura:

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

Ahora voy al proyecto donde quiero usar esto como biblioteca y escribo: npm install ./project-1.0.0.tgz

Se instala con éxito.

Ahora creo un archivo index.tsen mi proyecto donde acabo de instalar el npm import Project = require("project");

Escribir Project.me da las opciones de Intellisense, que fue el objetivo de todo este ejercicio.

Espero que esto ayude a alguien más a usar sus proyectos npm de TypeScript como bibliotecas internas en sus proyectos más grandes.

PD: Creo que este enfoque de compilar proyectos en módulos npm que se pueden usar en otros proyectos recuerda al .dlldel .NETmundo. Bien podría imaginar que los proyectos se organizan en una solución en VS Code donde cada proyecto produce un paquete npm que luego se puede usar en otro proyecto en la solución como una dependencia.

Como me tomó bastante tiempo resolver esto, lo publiqué en caso de que alguien se quede atascado aquí.

También lo publiqué por un error cerrado en: https://github.com/npm/npm/issues/11546


Este ejemplo se ha subido a Github: vchatterji / tsc-seed

Varun Chatterji
fuente
¿Podrías subir un ejemplo en github? ¡Eso ayudaría mucho! :)
Han Che
3
Se ha subido un ejemplo a Github: github.com/vchatterji/tsc-seed
Varun Chatterji
¿Cómo se puede utilizar también en proyectos no mecanografiados?
SuperUberDuper
5

Debería publicar las fuentes originales mecanografiadas en lugar de la definición de tipo. En package.jsondejar que la perspectiva de la propiedad 'tipos' en el fichero * Ts.

*.d.ts son buenos para anotar las librerías JS existentes, pero como consumidor prefiero leer el código mecanografiado que cambiar entre definiciones de tipo y código JS generado de nivel inferior.

Sven Efftinge
fuente
1
El compilador de TypeScript parece no ser adecuado para eso hasta ahora. Vea este número github.com/Microsoft/TypeScript/issues/14479
Sven Efftinge
2
*.d.tsIncluir actualmente es la forma recomendada de hacerlo, aunque estoy de acuerdo con los beneficios de incluir *.tsarchivos, typescriptlang.org/docs/handbook/declaration-files/…
Tim
5

Sigo principalmente la sugerencia de Varun Chatterji

Pero, me gustaría mostrar un ejemplo completo con pruebas unitarias y cobertura de código y publicarlo npme importarlos usando javascriptotypescript

Este módulo está escrito usando typescript 2.2y es importante configurar el prepublishgancho para compilar el código usando tscantes de publicarlo en npm

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

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

Tim
fuente
1
Ese es un ejemplo muy útil, ¡gracias por compartir! Actualmente también estoy tratando de acostumbrarme a crear paquetes de esta manera.
Jeffrey Westerkamp
1
A julio de 2017, esta es la mejor estructura de proyecto con la que me he encontrado. Gracias a Tim y Varun Chatterji
adgang
3

Puede usar autodts para manejar la distribución y el uso de .d.tsarchivos de npm también sin el soporte del IDE de Atom.

autodts generate empaquetará todo el tuyo .d.tsagrupará archivos para publicarlos en npm, y manejará autodts linklas referencias a otros paquetes instalados, que no siempre pueden estar directamente debajo node_modulesen un proyecto más grande dividido en varios subpaquetes.

Ambos comandos leen sus configuraciones desde package.json y tsconfig.jsonen estilo "convención sobre configuración".

Hay otra respuesta en stackoverflow y una publicación de blog con más detalles.

jjrv
fuente