6

使用Vue Router 版本 4(目前在 vue-router-next repo 中的 beta.11 中),有一个关于如何使用 TypeScript 定义元字段自定义类型接口的文档页面

declare module 'vue-router' {
  interface RouteMeta {
    // is optional
    isAdmin?: boolean
    // must be declared by every route
    requiresAuth: boolean
  }
}

放置在 Vue shim 模块声明中。我的看起来像:

declare module '*.vue' {
  import { defineComponent } from 'vue';

  const component: ReturnType<typeof defineComponent>;
  export default component;
}

declare module 'vue-router' {
  interface RouteMeta {
    isPublic?: boolean;
  }
}

但是,这是行不通的。相反,这种定义接口的方式似乎覆盖了包附带的接口,或者更确切地说,声明“vue-router”模块似乎可以做到这一点。

定义自定义元字段类型的正确方法是什么?

4

1 回答 1

11

他们的文件是错误的,或者充其量是不完整的。

模块扩充使用与环境模块声明相同的语法, 并且仅当它位于模块文件本身时才被视为扩充。import根据 ECMAScript 规范,模块被定义为包含一个或多个顶级export语句的文件。

不是模块的文件中的片段完全符合您所注意到的。它取代了'vue-router'包的任何其他类型,而不是增加它们。但是我们想增加那个包的类型,而不是替换它们。

但是,declare module旨在作为声明而不是扩充的语句必须位于文件中,相反,它不是模块。也就是说,在一个包含任何顶级importexport语句的文件中。

要解决此问题,请将 移动declare module 'vue-router' {...}到单独的文件(例如augmentations.d.ts),并通过以 . 开头使该文件成为模块export {}

// augmenations.d.ts

// Ensure this file is parsed as a module regardless of dependencies.
export {}

declare module 'vue-router' {
  interface RouteMeta {
    // is optional
    isAdmin?: boolean
    // must be declared by every route
    requiresAuth: boolean
  }
}

现在让我们回过头来看看有问题的原始代码。

// shims-vue.d.ts

declare module '*.vue' {
  import { defineComponent } from 'vue';

  const component: ReturnType<typeof defineComponent>;
  export default component;
}

declare module 'vue-router' {
  interface RouteMeta {
    isPublic?: boolean;
  }
}

这两个declare module语句不能存在于同一个文件中,因为其中一个试图声明一个模块,'*.vue'而另一个试图增加一个。因此,我们将离开declare module '*.vue' {...}它所在的位置,因为它按预期运行。

于 2020-09-21T20:25:47.633 回答