如何在 Vue Router v4 中为自定义元字段声明 TypeScript 类型接口?

ux.*_*eer 4 typescript vue.js vue-router vuejs3 vue-router4

对于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
  }
}
Run Code Online (Sandbox Code Playgroud)

沿着 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;
  }
}
Run Code Online (Sandbox Code Playgroud)

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

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

Alu*_*dad 7

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

模块增强使用相同的语法作为环境模块 声明,并且仅认为是增强时,它是一个模块文件本身内。一个模块被定义的,如每ECMAScript规范,如含有一个或多个顶层文件importexport语句。

不是模块的文件中的代码段与您所注意到的完全相同。它取代了'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
  }
}
Run Code Online (Sandbox Code Playgroud)

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

// 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;
  }
}
Run Code Online (Sandbox Code Playgroud)

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