Escrevendo módulos NPM em Typescript


103

Estou trabalhando no meu primeiro módulo NPM. Eu trabalhei brevemente com o texto datilografado antes e um grande problema era que para muitos módulos não havia arquivos de definição disponíveis. Portanto, pensei que seria uma boa ideia escrever meu módulo em texto digitado.

No entanto, não consigo encontrar nenhuma informação sobre a melhor maneira de fazer isso. Encontrei esta questão relacionada " Posso escrever pacote npm em coffeescript? ", Onde as pessoas sugerem publicar apenas os arquivos javascript. Mas, em contraste com os arquivos coffeescript, os arquivos datilografados podem realmente ser úteis se forem usados ​​em um aplicativo datilografado.

Devo incluir arquivos Typescript ao publicar um módulo NPM ou devo apenas publicar os arquivos javascript e fornecer os arquivos .d.ts gerados para DefinitelyTyped?


2
Notas úteis: escrevi o projeto, copee , junto com uma postagem no blog para orientá-lo na configuração de um projeto TS para emitir definições de tipo junto com os destinos CJS e ESM antes de publicar no npm. Isso irá maximizar o uso com node.js e navegadores daqui para frente.
elegante de

Respostas:


84

Aqui está um módulo de Node de amostra escrito em TypeScript: https://github.com/basarat/ts-npm-module

Aqui está um projeto TypeScript de amostra que usa este módulo de amostra https://github.com/basarat/ts-npm-module-consume

Basicamente, você precisa:

  • compilar com commonjsedeclaration:true
  • gerar um .d.tsarquivo

E depois

  • Faça com que seu ide leia o gerado .d.ts.

O Atom-TypeScript fornece apenas um bom fluxo de trabalho em torno disso: https://github.com/TypeStrong/atom-typescript#packagejson-support


O link de âncora Atom-TypeScript precisa ser atualizado (a âncora não é mais válida).
Fidan Hakaj

@basarat, no módulo ts-npm você está usando a "versão": "1.5.0-alpha". Presumo que esta seja a versão do Typescript com a qual você está transpilando. Importa deixar isso de fora? (não é feito automaticamente pelo plugin Atom). Se uma versão for usada, isso exigirá que outros usuários usem a versão exata para transpilar (ou apenas as mais recentes)? (ou talvez seja a versão do tsconfig.json?)
justin

Você tem algum caso de uso com módulos dependendo de outras bibliotecas? Para evitar o problema de definição duplicada, você precisa configurar tsconfig.json, mas isso parece muito manual na minha opinião.
Sérgio Michels

1
você ainda defenderia essa abordagem no quarto trimestre de 2016?
SuperUberDuper

7
Este foi um bom tutorial
chrismarx

78

Com TypeScript 3.x ou TypeScript 2.x, as etapas a seguir descrevem o que você deve fazer para criar uma biblioteca (pacote npm) com TypeScript:

  • Crie seu projeto como faria normalmente (com testes e tudo)
  • Adicione declaration: truea tsconfig.jsonpara gerar tipificações.
  • Exporte a API por meio de um index.ts
  • No package.json, aponte para suas digitações geradas. Por exemplo, se você outDirfor dist, adicione "types": "dist/index.d.ts"ao seu pacote json.
  • No package.json, aponte para o arquivo de entrada principal. Por exemplo, se o seu outDiré diste o arquivo de entrada principal for index.js, adicione "main": "dist/index.js"ao seu package.json.
  • Crie um .npmignorepara ignorar arquivos desnecessários (por exemplo, a fonte).
  • Publique no npm com npm publish. Use as especificações do Semver para atualizações (correção de patch / bug npm version patch, adições npm version minorininterruptas, alterações de API de interrupção npm version major)

Já que demorei um pouco para vasculhar todos os recursos desatualizados sobre este tópico na internet (como o desta página ...), decidi encerrá-lo em como escrever uma biblioteca typecript com um exemplo mínimo de trabalho atualizado.


Terei que verificar o js no controle de origem? Ou o npm mantém sua própria versão do código?
Olian04 de

1
@ Olian04 Você diz para criar um .npmignorearquivo para dizer ao npm quais arquivos ignorar ao publicar (os .tsarquivos) e um .gitignorepara dizer ao git quais arquivos ignorar ( dist/)
Purag

@ Olian04 não, você não precisa (e o IMO não deveria) enviar o (s) arquivo (s) JS gerado (s). Esses não fazem parte da fonte do projeto.
Josh M.

59

Esta é uma resposta mais recente usando TypeScript 1.8.10:

A estrutura do meu projeto é:

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

Eu adicionei o seguinte .npmignorepara evitar a inclusão de arquivos estranhos e manter o mínimo para ter o pacote importado e funcionando:

node_modules/
*.log
*.tgz

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

Meu .gitignoretem:

typings

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

Meu package.jsontem:

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

Agora eu corro: npm pack

O arquivo resultante (quando descompactado) tem a seguinte estrutura:

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

Agora vou para o projeto em que desejo usar isso como uma biblioteca e digito: npm install ./project-1.0.0.tgz

É instalado com sucesso.

Agora eu crio um arquivo index.tsno meu projeto onde acabei de instalar o npm import Project = require("project");

A digitação Project.me dá as opções do Intellisense, que foi o objetivo de todo este exercício.

Espero que isso ajude alguém a usar seus projetos npm do TypeScript como bibliotecas internas em seus projetos maiores.

PS: Eu acredito que esta abordagem de compilação de projetos para módulos NPM que podem ser usadas em outros projetos é uma reminiscência do .dllno .NETmundo. Eu poderia muito bem imaginar projetos sendo organizados em uma Solução no Código VS onde cada projeto produz um pacote npm que pode então ser usado em outro projeto na solução como uma dependência.

Como demorei um bom tempo para descobrir isso, eu postei para o caso de alguém estar preso aqui.

Eu também postei para um bug fechado em: https://github.com/npm/npm/issues/11546


Este exemplo foi enviado ao Github: vchatterji / tsc-seed


você poderia enviar um exemplo no github? Isso ajudaria bastante! :)
Han Che

3
Exemplo foi enviado ao Github: github.com/vchatterji/tsc-seed
Varun Chatterji

Como também pode ser usado em projetos não digitados?
SuperUberDuper

5

Você deve publicar as fontes originais do texto datilografado em vez da definição do tipo. Em package.jsondeixar o ponto propriedade 'tipos' para o arquivo Ts *.

*.d.ts são bons para anotar bibliotecas JS existentes, mas como consumidor, prefiro ler o código do texto digitado do que alternar entre as definições de tipo e o código JS gerado de nível inferior.


1
O compilador TypeScript parece não ser adequado para isso até agora. Consulte este problema github.com/Microsoft/TypeScript/issues/14479
Sven Efftinge

2
atualmente, incluir *.d.tsé a maneira recomendada de fazê-lo, embora eu concorde com você os benefícios de incluir *.tsarquivos, typescriptlang.org/docs/handbook/declaration-files/…
Tim

5

Eu sigo principalmente a sugestão de Varun Chatterji

Mas, gostaria de mostrar um exemplo completo com teste de unidade e cobertura de código e publicá-lo npme importá-los usando javascriptoutypescript

Este módulo é escrito usando typescript 2.2e é importante configurar o prepublishgancho para compilar o código usando tscantes de publicá-lo no npm

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

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


1
Esse é um exemplo muito útil, obrigado por compartilhar! No momento, também estou tentando pegar o jeito de criar pacotes dessa maneira.
Jeffrey Westerkamp,

1
Em julho de 2017, esta é a melhor estrutura de projeto que já encontrei. Agradecimentos a Tim e Varun Chatterji
adgang

3

Você pode usar autodts para lidar com a distribuição e uso.d.ts arquivos do npm, também sem suporte do IDE Atom.

autodts generateirá agrupar todos os seus próprios .d.tsarquivos para publicação no npm e autodts linklidar com referências a outros pacotes instalados, que nem sempre podem estar diretamente node_modulesem um projeto maior dividido em vários subpacotes.

Ambos os comandos lêem suas configurações de package.jsone tsconfig.jsonno estilo "convenção sobre configuração".

outra resposta sobre stackoverflow e uma postagem de blog com mais detalhes.


Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.