¿Cómo se produce un archivo de definición de "tipings" .d.ts a partir de una biblioteca JavaScript existente?

192

Estoy usando muchas bibliotecas tanto propias como de terceros. Veo que el directorio "tipings" contiene algunos para Jquery y WinRT ... pero ¿cómo se crean?

Hotrodmonkey
fuente

Respuestas:

232

Hay algunas opciones disponibles para usted dependiendo de la biblioteca en cuestión, cómo está escrita y qué nivel de precisión está buscando. Repasemos las opciones, en un orden de deseabilidad aproximadamente descendente.

Quizás ya exista

Siempre verifique DefinitelyTyped ( https://github.com/DefinitelyTyped/DefinitelyTyped ) primero. Este es un repositorio comunitario lleno de literalmente miles de archivos .d.ts y es muy probable que lo que estás usando ya esté allí. También debe verificar TypeSearch ( https://microsoft.github.io/TypeSearch/ ), que es un motor de búsqueda para archivos .d.ts publicados por NPM; esto tendrá un poco más de definiciones que DefinitelyTyped. Algunos módulos también envían sus propias definiciones como parte de su distribución NPM, así que también vea si ese es el caso antes de intentar escribir la suya.

Quizás no necesites uno

TypeScript ahora admite el --allowJsindicador y hará más inferencias basadas en JS en archivos .js. Puede intentar incluir el archivo .js en su compilación junto con la --allowJsconfiguración para ver si esto le proporciona información de tipo suficientemente buena. TypeScript reconocerá cosas como las clases de estilo ES5 y los comentarios de JSDoc en estos archivos, pero puede tropezarse si la biblioteca se inicializa de manera extraña.

Comience con --allowJs

Si --allowJste dio resultados decentes y desea escribir un archivo de definición mejor a sí mismo, se puede combinar --allowJscon --declarationver "mejor estimación" de mecanografiado en los tipos de la biblioteca. Esto le dará un punto de partida decente, y puede ser tan bueno como un archivo creado a mano si los comentarios de JSDoc están bien escritos y el compilador pudo encontrarlos.

Comience con dts-gen

Si --allowJsno funcionó, es posible que desee utilizar dts-gen ( https://github.com/Microsoft/dts-gen ) para obtener un punto de partida. Esta herramienta utiliza la forma de tiempo de ejecución del objeto para enumerar con precisión todas las propiedades disponibles. En el lado positivo, esto tiende a ser muy preciso, pero la herramienta aún no admite el raspado de los comentarios JSDoc para completar tipos adicionales. Ejecutas esto así:

npm install -g dts-gen
dts-gen -m <your-module>

Esto generará your-module.d.tsen la carpeta actual.

Presiona el botón de posponer

Si solo quiere hacerlo todo más tarde y no usar tipos por un tiempo, en TypeScript 2.0 ahora puede escribir

declare module "foo";

que te permitirá importel "foo"módulo con tipo any. Si tiene un global con el que desea tratar más tarde, solo escriba

declare const foo: any;

que te dará una foovariable.

Ryan Cavanaugh
fuente
25
Ouch ... eso será una barrera importante para la entrada en muchos casos. Sería bueno tener una herramienta que pudiera generar al menos "mejores conjeturas" basadas en la inferencia de tipos. Si bien estos pueden no ser óptimos, al menos podrían ajustarse con el tiempo.
Hotrodmonkey
77
+1 - Buenas noticias: --declarationsgenera tanto el .jsarchivo como el .d.tsarchivo, lo que significa que solo necesita ejecutar una sola compilación.
Fenton
67
Puede encontrar una colección de definiciones de alta calidad para bibliotecas populares en github.com/borisyankov/DefinitelyTyped
Boris Yankov
10
Una herramienta de 'mejor estimación' no será mejor que la IntelliSense ya existente en TypeScript. El beneficio de las definiciones de tipo radica en proporcionar más información al compilador de la que puede "adivinar".
Boris Yankov
12
--allowJscon --declarationopciones no se pueden combinar (probado en TypeScript 1.8 y 2.0). Si lo intento, obtengo:error TS5053: Option 'allowJs' cannot be specified with option 'declaration'
Alexey
52

Puede usar tsc --declaration fileName.tscomo lo describe Ryan, o puede especificar declaration: truedebajo compilerOptionsen su tsconfig.jsonsuposición de que ya ha tenido un tsconfig.jsonproyecto.

JayKan
fuente
44
Esta es la mejor respuesta si está desarrollando un módulo (s) Angular 2 que le gustaría compartir.
Darcy
Si lo intento tsc --declaration test.ts, aparece el error Cannot find name...para los tipos para los que estoy tratando de crear un archivo de declaración :) ¿Necesito los tipos antes de poder declararlos?
Kokodoko
2
@Kokodoko, ¿puedes intentar agregar declaration: truea tu tsconfig.jsonarchivo?
JayKan
Gracias, solo quería generar * .d.ts a partir de * .ts.
vintproykt
16

La mejor manera de lidiar con esto (si un archivo de declaración no está disponible en DefinitelyTyped ) es escribir declaraciones solo para las cosas que usa en lugar de toda la biblioteca. Esto reduce mucho el trabajo, y además el compilador está ahí para ayudar al quejarse de los métodos faltantes.

Gorgi Kosev
fuente
15

Como dice Ryan, el compilador tsc tiene un interruptor --declarationque genera un .d.tsarchivo a partir de un .tsarchivo. También tenga en cuenta que (salvo errores) se supone que TypeScript puede compilar Javascript, por lo que puede pasar el código javascript existente al compilador tsc.

CCoder
fuente
1
parece que actualmente pasa archivos * .js a tsc genera un error "Error al leer el archivo" angular-resource.js ": archivo no encontrado". Por lo tanto, debe renombrar explícitamente los archivos * .js a * .ts para poder usar tsc. Consulte este problema para obtener más detalles. Intenté usar esto en angularjs: typescript.codeplex.com/workitem/26
James Strachan el
3
por lo que puedo decir, tsc puede compilar cualquier JavaScript válido, pero si no es TypeScript válido (la compilación da advertencias), el indicador --declarations no genera un archivo .d.ts, por lo que a menos que su biblioteca esté escrita en TypeScript usted Todavía es necesario crear manualmente el archivo de declaraciones.
agradl
3

Aquí hay algunos PowerShell que crean un único archivo de definición de TypeScript, una biblioteca que incluye varios *.jsarchivos con JavaScript moderno.

Primero, cambie todas las extensiones a .ts.

Get-ChildItem | foreach { Rename-Item $_ $_.Name.Replace(".js", ".ts") }

Segundo, use el compilador TypeScript para generar archivos de definición. Habrá un montón de errores de compilación, pero podemos ignorarlos.

Get-ChildItem | foreach { tsc $_.Name  }

Finalmente, combine todos los *.d.tsarchivos en uno index.d.ts, eliminando las importdeclaraciones y eliminando las defaultde cada declaración de exportación.

Remove-Item index.d.ts; 

Get-ChildItem -Path *.d.ts -Exclude "Index.d.ts" | `
  foreach { Get-Content $_ } | `
  where { !$_.ToString().StartsWith("import") } | `
  foreach { $_.Replace("export default", "export") } | `
  foreach { Add-Content index.d.ts $_ }

Esto termina con un único index.d.tsarchivo utilizable que incluye muchas de las definiciones.

Shaun Luttin
fuente
2
Segundo paso, Get-ChildItem | foreach {tsc --declaration $ _. Name} trabajado (faltante agregado
parámetro de
3

Al crear su propia biblioteca, puede crear *.d.tsarchivos utilizando el tsccomando (Compilador TypeScript) de la siguiente manera: (suponiendo que esté creando su biblioteca en la dist/libcarpeta)

tsc -d --declarationDir dist/lib --declarationMap --emitDeclarationOnly
  • -d( --declaration): genera los *.d.tsarchivos
  • --declarationDir dist/lib: Directorio de salida para archivos de declaración generados.
  • --declarationMap: Genera un mapa fuente para cada archivo '.d.ts' correspondiente.
  • --emitDeclarationOnly: Solo emite archivos de declaración '.d.ts'. (sin compilación JS)

(vea los documentos para todas las opciones del compilador de línea de comandos)

O por ejemplo en tu package.json:

"scripts": {
    "build:types": "tsc -d --declarationDir dist/lib --declarationMap --emitDeclarationOnly",
}

y luego ejecuta: yarn build:types(o npm run build:types)

magikMaker
fuente
Todavía no puedo entender cómo generar los d.tsarchivos y poder usar interfaces. ¿Tienes algún ejemplo?
Danosaure
El script npm anterior generará los *.d.tsarchivos y los colocará en la dist/libcarpeta. Necesita un tsconfig.jsonarchivo en la raíz de su proyecto, pero de todos modos debería estar allí para que el proyecto funcione.
magikMaker
No puedo usarlos, una vez expuestos. Tengo la siguiente publicación stackoverflow.com/questions/59742688 si puedes hacer que funcione.
Danosaure
2

Buscaría una asignación existente de sus bibliotecas JS de terceros que admitan Script # o SharpKit. Los usuarios de estos compiladores cruzados de C # a .js habrán enfrentado el problema que ahora enfrentan y podrían haber publicado un programa de código abierto para escanear su lib de terceros y convertirlas en esqueletos de clases de C #. Si es así, piratee el programa del escáner para generar TypeScript en lugar de C #.

De lo contrario, traducir una interfaz pública de C # para su biblioteca de terceros a definiciones de TypeScript podría ser más simple que hacer lo mismo leyendo el código fuente JavaScript.

Mi interés especial es el marco ExtJS RIA de Sencha y sé que se han publicado proyectos para generar una interpretación de C # para Script # o SharpKit

el caso de Carmel
fuente
FYI: Acabo de hacer mi primer archivo de definición de mecanografía para Sencha / ExtJS: github.com/andremussche/extjsTypescript/blob/master/jsondocs/…
André
Hola, Camel Case, he creado un blog sobre el uso de ExtJs con mecanografiado: blorkfish.wordpress.com/2013/01/28/using-extjs-with-typescript
blorkfish