¿Cómo “importar” un typedef de un archivo a otro en JSDoc usando Node.js?

4 minutos de lectura

Avatar de usuario de FireController1847
Controlador de fuego1847

Digamos que tengo un archivo llamado “File1.js”. En este archivo, exporto un objeto de objetos y le doy a cada objeto un typedef, así.

/**
 * My typedef for each object.
 * @typedef {Object} MyObject1
 * @property {String} username Your username
 * @property {String} realname Your real name.
 * @property {boolean} isUnique Are you unique as a person?
 */
module.exports = {
  /**
   * Person One!
   * @type {MyObject1}
   */
  myperson: {
    username: 'TheDragonSlayer',
    realname: 'George',
    isUnique: true
  },
  /**
   * Person Two!
   * @type {MyObject1}
   */
  myperson2: {
    username: 'BobMagee',
    realname: 'Bob',
    isUnique: false
  }
}

Ahora, en un archivo llamado “File2.js”, hago referencia a este objeto en un constructor y lo establezco en un nuevo MyObject1.

const persons = require('./File1.js');

class File2 {
  constructor(options = {}) {
    /**
     * The person for this file.
     * @type {MyObject1}
     */
    this.person = options.person ? persons[options.person] : persons.myperson2;
  }
}

module.exports = File2;

Uso Visual Studio Code para desarrollar, por lo que al presionar Ctrl+Espacio obtengo IntelliSense. Dentro del archivo uno y mientras hago los objetos person, IntelliSense me dice que el nombre de usuario es una cadena, realname es una cadena e isUnique es un valor booleano. Pero, cuando entro en el archivo 2 y hago referencia a la persona recién creada a través de this.personal escribir this.person.username no presenta el resultado esperado de “Nombre de usuario: Cadena”.

¿Es posible usar el typedef? MyObject1 en File2 en vanilla Node.js, ¿o no tengo suerte?

Editar: con algo más de información, pude encontrar respuestas con @export y @import para TypeScript, así como una especie de etiqueta que también probé. Todo lo cual fue en vano. También intenté marcar File1.js como @module y hacer module:mymodule~MyMethodpero cada vez que lo hacía, simplemente marcaba this.person como NodeModule en lugar del método en sí.

  • Querías decir @typedef en lugar de @typdef en Archivo1?

    – Pedro G.

    14/04/2018 a las 22:42

  • @PeterG ¡Sí, lo siento!

    – Controlador de fuego1847

    14/04/2018 a las 22:47

  • Puede ser solo una cuestión de qué tan inteligente es Intellisense en lugar de una cosa de JSDoc. Usando WebStorm IDE, encontré que este escenario funciona como se esperaba, pero a menudo encuentro límites en el soporte de JSDoc; por ejemplo, no funciona como se esperaba cuando @typedef está en un proyecto de dependencia.

    –Justin Emery

    19 de abril de 2018 a las 8:55

  • Hay un comentario a este efecto en la respuesta a continuación, pero import("some-module") es compatible con Typescript pero es no JSDoc oficial.

    – Codificador

    21 de enero de 2021 a las 11:22

  • También usando import "./types.js" y @typedef en el archivo types.js funciona para mí.

    – aderchox

    15/09/2022 a las 17:08

Importe el tipo declarado en su archivo File2.js usando la función import.

const persons = require('./File1.js');

/**
 * @typedef {import('./File1.js').MyObject1} MyObject1
 */

class File2 {
...

Esto funciona para mi.

ingrese la descripción de la imagen aquí
ingrese la descripción de la imagen aquí

  • ¡Impresionante! ¡Esto realmente lo arregló! ¡Muchas gracias!

    – Controlador de fuego1847

    17 de octubre de 2018 a las 5:11

  • Esta es una sintaxis específica de TypeScript. Vota por github.com/jsdoc/jsdoc/issues/1645.

    – cañada-84

    28 de mayo de 2020 a las 10:42

  • Documentos oficiales para tipos de importación: typescriptlang.org/docs/handbook/…

    – Georgiy Bujarov

    22 de noviembre de 2021 a las 10:41


  • Cualquier forma de no escribir repetidamente import('./File1.js')? (si necesito, por ejemplo, también file1.MyObject2 y file1.MyObjectN). – Haciendo @typedef {import('./File1.js')} file1 y @typedef {file1.MyObject2} MyObject2 MyObject2 solo tiene alias y pierde detalles de definición, se marca como /*unresolved*/ any.

    – Kamapluma

    29 ago 2022 a las 16:00


Otra cosa que descubrí trabajando es exportar y vaciar el modelo y luego usarlo como referencia a los tipos:

tipos.js:

/** 
* @typedef MyType 
* @prop {string} name  
* @prop {string} description 
*/

export const Types = {}

Luego, en sus otros archivos, puede importar eso y tener los tipos de ese objeto ficticio:

Archivo1.js

import * as Types from "./types.js"

/** @type {Types.MyType} */
const myVar = { name : 'Roy', description : 'abc123'};

ventajas:

  • mucho “limpio” – menos código para escribir
  • solo hay que importar una vez

contras:

  • un poco raro
  • no idiomático
  • es posible que obtenga el error:

Esta importación nunca se usa como un valor y debe usar ‘tipo de importación’ porque ‘importsNotUsedAsValues’ está establecido en ‘error’

Si tienes esa bandera puesta.

Para sortear esa advertencia, solo necesita deshabilitarla con un ts-ignore:

// @ts-ignore  
import * as Types from "./types.js";

¿Ha sido útil esta solución?