如何将属性添加到数组类型?

时间:2018-09-05 17:25:24

标签: typescript

在Vue中,我们具有以下类型:

Vue.$refs: {
    [key: string]: Vue | Element | Vue[] | Element[];
}

我有一个第三方库(vuelidate),它为所有Vue添加了一个$v属性。它没有定义类型,所以我自己做。

declare module 'vue/types/vue' {
  interface Vue {
    $v: any
  }

  interface Element {
    $v: any
  }
}

当我尝试在$ refs上使用$v时,打字稿抱怨:

this.$refs.form.$v

结果

Property '$v' does not exist on type 'Vue[]'.

这对我来说很有意义。但是,没有意义的是如何向Vue[]Element[]添加属性,以便编译此代码。


我已经遍历了文档“ Stack Overflow”,您为它起了名字,但我找不到解决方案。如何将类型添加到特定数组?

我了解为什么这行不通:

interface Vue[] {
  $v: any
}

但是我不知道该如何解决。

1 个答案:

答案 0 :(得分:1)

强制转换有效,但是我很感谢您希望声明类型,因此您不必每次都强制转换。 Vue[]实际上是Array<Vue>的缩写,Array是内置通用接口Array的参数化。您可以将属性添加到Vue[],但是随后将在所有类型的数组上声明它们,而不仅仅是// Wrap with `declare global { ... }` if the file is an ES6 module interface Array<T> { $v: T extends Vue | Element ? any : unknown; } 。您可以使用条件类型来缓解这种情况,如下所示:

$v

但实际上,您不希望每个Vue[]上都有Vue.$refs,而只希望Vue.$refs上。不幸的是,考虑到声明vue的方式,我不认为有任何方法可以通过扩充来进行此更改。您必须在项目中添加export interface Vue { // ... readonly $refs: { [key: string]: (Vue | Element | Vue[] | Element[]) & {$v: any} }; // ... } 软件包的修改版本,并将声明更改为:

vuelidate

显然,此更改不适合向上游发送。但是您可以发送PR来添加一个钩子,以便其他软件包(例如// In vue/types/vue.d.ts: export interface RefExtra {} export interface Vue { // ... readonly $refs: { [key: string]: (Vue | Element | Vue[] | Element[]) & RefExtra }; // ... } // In vuelidate typings (or your project for now): declare module 'vue/types/vue' { interface RefExtra { $v: any } } )可以增强:

git add <folder>/*