Escribiendo un archivo de declaración de TypeScript para un paquete externo de Node.js en JavaScript, sin información de tipos
Estoy escribiendo una biblioteca de Node.js en TypeScript (para usar en el contexto de una aplicación CLI) que tiene una dependencia de una biblioteca JS llamada jinxed, que no tiene declaraciones de tipos de TypeScript. He estado siguiendo la información sobre archivos de declaración de TypeScript.
jinxed es una biblioteca sencilla que actualmente exporta una única función mediante module.exports { ... }, no está destinada a ser la única exportación de la biblioteca (ya que se expandirá en el futuro). Por lo tanto, la función exportada es un miembro del objeto de exportación.
El problema es cómo puedo consumir esto dentro de una biblioteca de TypeScript. Después de leer toda la documentación de declaraciones de TypeScript, todavía no me queda claro cómo hacerlo.
El primer problema a resolver es qué plantilla de declaración elegir de las plantillas de archivos de declaración de Typescript.
Decidí que la plantilla apropiada para usar y permitir consumir jinxed desde TypeScript es module.d.ts (aunque estoy abierto a que me corrijan).
Así que mi biblioteca cliente de TypeScript (widget) se ve así:
widget/
lib/
externalTypes/
jinxed/
index.d.ts
index.ts
Entonces, lo anterior me muestra definiendo un archivo de tipos para la dependencia externa jinxed según las instrucciones en el archivo de plantilla; es decir, crear una carpeta cuyo nombre coincida con el nombre de la dependencia externa y colocar un archivo index.d.ts dentro de ella.
widget/lib/externalTypes/jinxed/index.d.ts:
exportar función functify(obj: any): string;
En el lado del consumidor; es decir, dentro de mi archivo index.ts (widget/lib/index.ts):
/// <reference types="./externalTypes/jinxed" />
import jinxed = require('jinxed');
const TestObject:any = {
name: 'dvorak',
occ: 'watchman'
};
jinxed.functify(TestObject);
[PD: También he intentado:
let jinxed=require('./externalTypes/jinxed'); ( ... pero esto solo resulta en un error sobre el uso de la sentencia require)
]
Pero al compilar se produce el siguiente mensaje de error:
ERROR en /Users/User/dev/github/js/widget/lib/index.ts ./lib/index.ts [tsl] ERROR en
/Users/User/dev/github/js/widget/lib/index.ts(4,25) TS7016: No se pudo encontrar un archivo de declaración para el módulo 'jinxed'. '/Users/User/dev/github/js/widget/node_modules/jinxed/index.js' tiene implícitamente un tipo 'any'.
(Disculpas por el mensaje de error que se ve un poco feo, problemas de formato)
[
Y para mayor completitud, el contenido de jinxed es el siguiente:
'use strict';
function functify (obj) {
return JSON.stringify(obj, (key, val) => {
return (typeof val === 'function') ? '_function_' : val;
});
}
module.exports = {
functify: functify
}
]
El mensaje de error indica que no puede encontrar el archivo de declaración para jinxed, pero he usado el
/// <reference...
para especificar el tipo de archivo a usar, así que no sé cuál es el problema.
Las dependencias en widget package.json son las siguientes:
"dependencies": {
"@types/ramda": "^0.26.19",
"jinxed": "0.0.1",
"ramda": "^0.26.1",
"xpath": "0.0.27" },
El archivo tsconfig es:
{
"compilerOptions": {
"allowJs": true,
"alwaysStrict": true,
"module": "commonjs",
"moduleResolution": "Node",
"noImplicitAny": true,
"sourceMap": true,
"strictNullChecks": true,
"target": "es5",
"types": [],
"lib": [
"es5",
"es2015",
"es6",
"dom"
]
},
"include": [
"lib/**/*"
],
"exclude": [
"node_modules",
"**/*.spec.ts"
]
}
La entrada "main" en package.json es:
"main": "./lib/index.ts",
Además, me gustaría saber si la forma en que he estructurado las dependencias de tipos externos parece razonable. Es decir, digamos que estoy tratando de utilizar otra biblioteca js externa de manera similar a la ilustrada arriba para jinxed; asumiría que crearía otra carpeta bajo externalTypes que coincida con el nombre de esa dependencia y la llenaría con su propio index.d.ts. ¿Es eso correcto o estoy yendo por mal camino?
EDIT: (Encontré la solución a este problema a través de este tema, pero realmente no entiendo esto.
En el archivo index.d.ts, lo he actualizado para que sea como sigue:
declare module 'jinxed' {
export function functify(obj: any): string;
}
... y esto realmente funciona.
Sin embargo, no entiendo la declaración declare module, en particular, por qué los nombres jinxed están entre comillas (quita las comillas y obtienes un error: TS7016: No se pudo encontrar un archivo de declaración para el módulo 'jinxed'). Hasta ahora no he encontrado la plantilla correcta de TypeScript a la que esto corresponda, así que no puedo obtener una buena explicación de por qué esto funciona.
Respuesta #1
Parece que encontraste la respuesta a tu pregunta original, pero pensé en compartir algunos recursos sobre tu segunda pregunta. Según la documentación de TypeScript: Módulos Ambientales
En Node.js, la mayoría de las tareas se realizan cargando uno o más módulos. Podríamos definir cada módulo en su propio archivo .d.ts con declaraciones de exportación a nivel superior, pero es más conveniente escribirlos como un solo archivo .d.ts más grande. Para hacerlo, usamos una estructura similar a los namespaces ambientales, pero usamos la palabra clave module y el nombre entre comillas del módulo que estará disponible para una importación posterior.
Los declare module son palabras clave del lenguaje, y la cadena es el nombre del módulo que estás importando.