【问题标题】:TypeScript Declarations ConflictTypeScript 声明冲突
【发布时间】:2021-08-11 09:52:27
【问题描述】:

复制:https://github.com/wenfangdu/d-ts-conflict-repro

shims-vue.d.ts

/* eslint-disable */
declare module '*.vue' {
  import type { DefineComponent } from 'vue'
  const component: DefineComponent<{}, {}, any>
  export default component
}
/* eslint-enable */

import 'vue'

declare module 'vue' {
  interface HTMLAttributes extends interface {
    vModel?: unknown
  }
}

运行npm run serve,开发服务器启动后,打印出这些错误:

ERROR in src/main.ts:2:17
TS7016: Could not find a declaration file for module './App.vue'. 'D:/Repos/d-ts-conflict-repro/src/App.vue.js' implicitly has an 'any' type.
    1 | import { createApp } from 'vue'
  > 2 | import App from './App.vue'
      |                 ^^^^^^^^^^^
    3 | import router from './router'
    4 | import store from './store'
    5 |

ERROR in src/router/index.ts:17:46
TS7016: Could not find a declaration file for module '../views/About.vue'. 'D:/Repos/d-ts-conflict-repro/src/views/About.vue.js' implicitly has an 'any' type.
    15 |     // which is lazy-loaded when the route is visited.
    16 |     component: () =>
  > 17 |       import(/* webpackChunkName: "about" */ '../views/About.vue'),
       |                                              ^^^^^^^^^^^^^^^^^^^^
    18 |   },
    19 | ]
    20 |

我做错了什么?

【问题讨论】:

  • 你为什么要添加第二个声明?
  • @BoussadjraBrahim 我想在&lt;input /&gt; 上使用vModel
  • vue 指令可以作为 html 属性正常工作
  • @BoussadjraBrahim 我正在使用 TSX,v-model 是允许的,但 vModel 是不允许的,所以我不得不添加这个。如果我把它放在另一个.d.ts 中,一切正常,但是当它们在同一个.d.ts 中时它会抛出,我不明白为什么。
  • 但是为什么要使用vModel 而不是v-model

标签: typescript vue.js typescript-typings vuejs3 vue-cli


【解决方案1】:

声明declare module '*.vue' 应该在全局范围内。即非模块中的*声明(其中模块是具有至少一个*importexport 的文件)。

模块中declare module 'vue' 形式的声明是一种扩充。更多详情请见Typescript Module Augmentation

这两组声明应该存在于不同的文件中。

【讨论】:

    【解决方案2】:

    您必须执行以下操作:

    /* eslint-disable */
    declare module '*.vue' {
      import type { DefineComponent } from 'vue'
      const component: DefineComponent<{}, {}, any>
      export default component
    }
    /* eslint-enable */
    import * as vue from 'vue';
    declare module 'vue' {
      interface HTMLAttributes {
        vModel?: number;
      }
    }
    

    但是,这只会显示在 TypeScript 代码中,而不是 Vue 标记中。原因是标记从 Vue 插件而不是 TypeScript 语言服务中获取智能感知。

    【讨论】:

    • vModel 没有出现在 &lt;input /&gt; 属性 IntelliSense 中。
    • 我修复了答案,但您不会在 HTML 标记中得到 vModel。此外,默认情况下 HTML 标记不应该区分大小写,因此 v-model 是正确的约定。
    【解决方案3】:

    我已经在我的项目中进行了尝试,它的工作原理如下:

    declare module '*.vue' {
      import type { DefineComponent } from 'vue'
      const component: DefineComponent<{}, {}, any>
    
      export interface HTMLAttributes {
        vModel?: any;
      }
      export default component
    }
    

    【讨论】:

    • 非常感谢您的努力!但是,vModel 没有出现在 &lt;input /&gt; IntelliSense 中,您是否在 .tsx 文件中尝试过?
    • 尝试重新运行 npm run serve,我用 tsx 扩展尝试过