TypeScript Custom Type para JS lib, la importación no funciona

Sep 26 2020

Tengo un proyecto vue con mecanografiado y estoy importando un tipo personalizado que creo para vue-numeral-filter , pero esto genera el error:

ERROR en /Users/bmartins/Development/app-invest/src/main.ts(14,30): 14:30 No se pudo encontrar un archivo de declaración para el módulo 'vue-numeral-filter'. '/Users/bmartins/Development/app-invest/node_modules/vue-numeral-filter/dist/vue-numeral-filter.es.js' tiene implícitamente un tipo 'any'. Pruebe npm install @types/vue-numeral-filtersi existe o agregue un nuevo archivo de declaración (.d.ts) que contengadeclare module 'vue-numeral-filter';

En mi archivo main.ts tengo:

import Vue from 'vue';
import App from './App.vue';
import Vuetify from 'vuetify';
import vuetify from './plugins/vuetify';
import router from './router';
import VueApexCharts from 'vue-apexcharts';
import Vuex from 'vuex';
import store from './store';
import { mockStore } from './test/mock/store';
import * as moment from 'moment';
import 'moment/locale/pt-br';
import VueMoment from 'vue-moment';
import { API_URL, PRODUCT_TYPES } from './store/constants';
import VueNumeralFilter from 'vue-numeral-filter';

Vue.component('apexchart', VueApexCharts);

Vue.use(Vuetify);
Vue.use(Vuex);
Vue.use(VueNumeralFilter, { locale: 'pt-br' });
Vue.use(VueMoment, {
  moment,
});

Para el tipo creo la estructura de carpetas:

App 
|_ src 
|_ types    
   |_ vue-numeral-filter
        |_ index.d.ts

Estructura de carpetas

El index.d.ts que creé basado en el @ types / vue-moment :

import Numeral from 'numeral';
import { PluginObject } from 'vue';

declare namespace VueNumeralFilterPlugin {
  interface Options {
    // The optional (self-maintained) numeral instance
    numeral?: Numeral;
  }
  interface VueStatic extends Numeral {
    (inp?: Numeral, format?: string): string;
    (inp?: Numeral): string;
  }
}

declare module 'vue-numeral-filter' {
  interface Vue {
    $numeral: VueNumeralFilterPlugin.VueStatic;
  }
}

type VueNumeralFilter = PluginObject<undefined>;

declare const VueNumeralFilter: VueNumeralFilter;
export = VueNumeralFilter;

Y la última parte fue cambiar el tsconfig.json:

{
  "compilerOptions": {
    "target": "esnext",
    "module": "esnext",
    "strict": true,
    "jsx": "preserve",
    "importHelpers": true,
    "moduleResolution": "node",
    "skipLibCheck": true,
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "sourceMap": true,
    "baseUrl": ".",
    "typeRoots": [
      "./types"
    ],
    "types": [
      "webpack-env",
      "vue-numeral-filter",
      "vuetify-form-base"
    ],
    "paths": {
      "@/*": [
        "src/*"
      ]
    },
    "lib": [
      "esnext",
      "dom",
      "dom.iterable",
      "scripthost"
    ]
  },
  "include": [
    "src/**/*.ts",
    "src/**/*.tsx",
    "src/**/*.vue",
    "tests/**/*.ts",
    "tests/**/*.tsx"
  ],
  "exclude": [
    "node_modules"
  ]
}

Leí esta publicación TypeScript 2: mecanografía personalizada para el módulo npm sin tipo , varias veces que tiene una explicación sorprendente pero aún no descubrí cómo solucionarlo ...

¿Alguna ayuda?

Respuestas

cjol Oct 05 2020 at 15:45

Los archivos de definición de tipos pueden ser un poco complicados en Typecript. Es muy fácil terminar escribiendo algo que TypeScript interpreta como un módulo en lugar de un archivo de declaración. Cuando esto sucede, TypeScript comienza a esperar que importe tipos del archivo directamente, en lugar de reconocer la declaración de tipo incrustado.

Me parece que su archivo de definición de tipo es incorrecto. En particular, tiene imports fuera de la declaración del módulo, que es uno de los indicadores que TypeScript reconoce como marcador de módulo. Si mueve sus imports para que estén dentro del declare { ... }bloque, creo que comenzará a funcionar.

En una nota diferente, creo que las entradas typeRootsy typesen su tsconfig.jsonarchivo son demasiado restrictivas. No creo que eso sea lo que está causando el problema aquí, pero creo que debería eliminarlos, de lo contrario, tendrá problemas para instalar tipos de terceros en el futuro.