JS lib的Typescript自定义类型,导入不起作用

Posted

技术标签:

【中文标题】JS lib的Typescript自定义类型,导入不起作用【英文标题】:Typescript Custom Type for JS lib, import not working 【发布时间】:2021-01-12 06:32:03 【问题描述】:

我有一个带有 typescript 的 vue 项目,并且我正在导入我为 vue-numeral-filter 创建的自定义类型,但这会产生错误:

/Users/bmartins/Development/app-invest/src/main.ts(14,30) 中的错误: 14:30 找不到模块“vue-numeral-filter”的声明文件。 '/Users/bmartins/Development/app-invest/node_modules/vue-numeral-filter/dist/vue-numeral-filter.es.js' 隐含了一个 'any' 类型。 尝试npm install @types/vue-numeral-filter(如果存在)或添加包含declare module 'vue-numeral-filter'; 的新声明(.d.ts)文件

在我的 main.ts 文件中,我有:

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,
);

对于我创建文件夹结构的类型:

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

Folder Structure

我基于@types/vue-moment创建的index.d.ts:

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;

最后一部分是更改 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"
  ]

我看了这篇TypeScript 2: custom typings for untyped npm module的帖子,看了好几遍,里面的解释很神奇,但还是不知道怎么解决……

有什么帮助吗?

【问题讨论】:

【参考方案1】:

Typescript 中的类型定义文件可能有点挑剔。很容易写出 TypeScript 解释为模块而不是声明文件的东西。发生这种情况时,TypeScript 开始期望您直接从文件中导入类型,而不是识别嵌入的类型声明。

在我看来,您的类型定义文件不正确。特别是,您在模块声明之外有 imports,这是 TypeScript 识别为模块标记的标志之一。如果你移动你的imports 使它们在declare ... 块内,我认为它会开始工作。

另一方面,我认为tsconfig.json 文件中的typeRootstypes 条目过于严格。我认为这不是导致问题的原因,但我认为您应该删除它们,否则您将来安装 3rd-party 类型将遇到问题。

【讨论】:

感谢您的回答!我还注意到,如果我采用确切的声明文件并移动到 @types 文件夹中的 node_module 它可以工作!似乎 node_modules 中的声明文件也有一些差异解释!

以上是关于JS lib的Typescript自定义类型,导入不起作用的主要内容,如果未能解决你的问题,请参考以下文章

Typescript自定义类型定义在导入类上中断

如何添加自定义 TypeScript 全局接口

将自定义库导入故事书

如何在打字稿中正确导入自定义类型

需要带有 npm 和 typescript 的自定义模块

找不到带有 Webpack、Typescript、自定义模块目录的模块