TS2339:类型“{}”上不存在属性“next”

时间:2021-02-24 21:31:29

标签: typescript vue.js

我在 Vue.js 应用程序上工作,其中一个组件的代码如下所示:

<template lang="pug">
  div
    b-container(v-if='displayRouletteControls')
      b-row
        b-col(:cols='1').d-flex.align-items-center.justify-content-center.cursor-pointer
          img(src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100' fill='%232E86C1' class='bi bi-chevron-left' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3E%3C/svg%3E" @click='onPrevious()')
        b-col(:cols='10')
          b-carousel(
            id='categoryRoulette'
            no-animation
            :interval='0'
            ref='myCarousel'
          )
            b-carousel-slide
              template(v-slot:img)
                b-card-group(deck)
                  b-card(
                    v-for="(item, index) in subArrayValues" :key="index"
                    :img-src="item.image ? item.image : '../assets/images/blank.png'"
                    img-alt='Image'
                    img-top
                    tag='article'
                  )
                    b-card-text.d-flex.justify-content-center.align-items-center
                      h5
                        a(href="#") {{ item.title }}
        b-col(:cols='1').d-flex.align-items-center.justify-content-center.cursor-pointer
          img(src="data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='100' height='100' fill='%232E86C1' class='bi bi-chevron-right' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3E%3C/svg%3E" @click='onNext()')
    b-container(v-else)
      b-row
        b-col
          b-carousel(
            id='categoryRoulette'
            :controls='displayRouletteControls'
            no-animation
            :interval='0'
          )
            b-carousel-slide(
              v-for="category in catalog"
              :key="category.permalink"
            )
              template(v-slot:img)
                b-card(
                  :img-src="category.image ? category.image : '../assets/images/blank.png'"
                  img-alt='Image'
                  img-top
                  tag='article'
                )
                  b-card-text.d-flex.justify-content-center.align-items-center
                    h5
                      a(href="#") {{ category.title }}
</template>

<script lang="ts">
import Vue from 'vue'
import { Category } from 'types'
import { RouletteData } from '../types/roulette'
import testData from '../data/testData.json'

function* subArrayGenerator(inputArray: Array<Category>, subArrayLength = 3) {
  let prev = false
  for (let i = 0; i < inputArray.length; ) {
    if (prev) {
      const diff = i - (subArrayLength - 3) * 2
      i = diff < 0 ? inputArray.length + diff : diff
    }
    const subArray = []
    for (let j = 0; j < subArrayLength; j++) {
      subArray.push(inputArray[i])
      i = i < inputArray.length - 1 ? i + 1 : 0
    }
    prev = (yield subArray) === false
  }
}

export default Vue.extend({
  data: (): RouletteData => ({
    catalog: [],
    displayRouletteControls: true,
    subArrayIterator: {},
    subArrayValues: {},
  }),
  mounted() {
    this.$nextTick(() => {
      window.addEventListener('resize', this.onResizeRoulette)
      this.onResizeRoulette()
    })
    this.catalog = testData.catalog
    this.subArrayIterator = subArrayGenerator(this.catalog)
    this.subArrayValues = this.subArrayIterator.next().value
  },
  beforeDestroy() {
    window.removeEventListener('resize', this.onResizeRoulette)
  },
  methods: {
    onPrevious() {
      this.subArrayValues = this.subArrayIterator.next(false).value
    },
    onNext() {
      this.subArrayValues = this.subArrayIterator.next().value
    },
    onResizeRoulette() {
      if (window.innerWidth >= 992) {
        this.displayRouletteControls = true
      } else {
        this.displayRouletteControls = false
      }
    },
  },
})
</script>

<style lang="sass">
.cursor-pointer
  cursor: pointer
.set-top-margin
  margin-top: 40px
#categoryRoulette
  margin-bottom: 40px
  margin-top: 40px
  .carousel-control-prev-icon
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%232E86C1' class='bi bi-chevron-left' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M11.354 1.646a.5.5 0 0 1 0 .708L5.707 8l5.647 5.646a.5.5 0 0 1-.708.708l-6-6a.5.5 0 0 1 0-.708l6-6a.5.5 0 0 1 .708 0z'/%3E%3C/svg%3E") !important
    height: 100px !important
    margin-left: calc(100% - 320px)
    width: 100px !important
  .carousel-control-next-icon
    background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='16' height='16' fill='%232E86C1' class='bi bi-chevron-right' viewBox='0 0 16 16'%3E%3Cpath fill-rule='evenodd' d='M4.646 1.646a.5.5 0 0 1 .708 0l6 6a.5.5 0 0 1 0 .708l-6 6a.5.5 0 0 1-.708-.708L10.293 8 4.646 2.354a.5.5 0 0 1 0-.708z'/%3E%3C/svg%3E") !important
    height: 100px !important
    margin-right: calc(100% - 320px)
    width: 100px !important
</style>

代码运行良好,但在 VS Code 中 next() 方法用红线标出。

enter image description here

更糟糕的事情发生在 GitLab CI/CD 工作中。

enter image description here

我对 TypeScript 的了解不多,但假设类型存在一些问题。

该组件的界面如下所示:

import { Category } from './index'
export interface RouletteData {
  catalog: Array<Category>
  displayRouletteControls: boolean
  subArrayIterator: {}
  subArrayValues: {}
}

我该如何解决这个问题?

更新:

我已经按照您的建议进行了更改,并得到了以下内容:

enter image description here

enter image description here

Category 界面如下所示:

export interface Category {
  title: string
  permalink: string
  hasChildren: boolean
  cover: string
  subcatalog?: Category[]
  image: string
}

1 个答案:

答案 0 :(得分:1)

您可以更改接口 RoutletteData 以添加有关 Next() 函数的信息。目前,它说 subArrayIterator 是一个对象,但没有指定关于它的其他类型信息。

export interface RouletteData {
    catalog: Array<Category>
    displayRouletteControls: boolean
    subArrayIterator: {
        next?(someBool?: boolean): {
            value: {}
        }
    },
    subArrayValues: {}
}

在上面,我们为 next() 属性定义了一个 subArrayIterator 函数。分解,定义如下:

next 这是函数名。

? 表示 next 是可选的 - 这允许您的 data() 保持原样,它不在 {{1} 上声明 next() 函数},它只是一个空对象。

subArrayIterator 这是 someBool?: boolean 函数的可选参数,布尔类型。 next 只是一个描述性名称,如果您知道布尔值表示什么,请给它一个更好的名称。

someBool 这是函数的返回类型。您的代码对 : { value: {} } 的结果调用 .value,因此您希望它具有 .next() 属性。我们不知道它的类型,但因为它被分配给 value,所以它必须与它兼容 - 我们暂时将其保留为空对象。

相关问题