将道具传递到设置时,VueJS3CompositionAPI和TypeScript类型问题:类型上不存在属性“用户”

我正在努力弄清楚我做错了什么才能让 TypeScript 理解它props.user的类型UserInterface,任何建议或指针都会很棒

vue@3.1.1、typescript@4.2.2、quasar@2.0.0-rc.3。这感觉更像是原生 VueJS 或 TypeScript 问题,而不是与 Quasar 有任何关系

参考用户界面:

export default interface UserInterface {
  id: number,
  email: string,
  name: string,
  agent_id: string
}

成分:

<template>
  <q-avatar :color="color" :text-color="textColor" :size="size" :title="user.name">
    {{ initials(user.name) }}
  </q-avatar>
</template>

<script lang="ts">
import UserInterface from 'logic/interfaces/UserInterface'
import {computed, defineComponent, PropType} from 'vue'

const colors: Record<string, string> = {
  A: 'blue',
  K: 'black',
  R: 'purple',
  S: 'primary'
}

export default defineComponent({
  name: 'UserIcon',
  props: {
    user: {
      type: Object as PropType<UserInterface>,
      required: true
    },
    size: {
      type: String,
      required: false,
      default: 'lg',
      validator: function (value: string) {
        return ['xs', 'sm', 'md', 'lg', 'xl'].indexOf(value) !== -1
      }
    },
    textColor: {
      type: String,
      required: false,
      default: 'white'
    }
  },
  setup (props) {
    const initial = props.user.agent_id.charAt(0)
    const color = computed(() => {
      return colors[initial] || 'green'
    })

    return {
      color,
      initials (name: string) {
        const names = name.split(' ')
        let initials = names[0].charAt(0)
        if (names.length > 1) {
          initials += names[names.length - 1].charAt(0)
        }

        return initials
      }
    }
  }
})
</script>

VueJS 3 文档https://v3.vuejs.org/guide/typescript-support.html#using-with-composition-api指出:

在 setup() 函数中,您不需要将类型传递给 props 参数,因为它会从 props 组件选项推断类型。

但是,我不断收到并发症错误,我不确定我错过了什么

结果:

Failed to compile.

TS2339: Property 'user' does not exist on type 'Readonly<LooseRequired<Readonly<{ [x: number]: string; } & { length?: number | undefined; toString?: string | undefined; toLocaleString?: string | undefined; concat?: string[] | undefined; join?: string | undefined; ... 15 more ...; includes?: ((searchElement: string, fromIndex?: number | undefined) => boolean) | un...'.
    38 |   },
    39 |   setup (props) {
  > 40 |     const initial = props.user.agent_id.charAt(0)
       |                           ^^^^
    41 |     const color = computed(() => {
    42 |       return colors[initial] || 'green'
    43 |     })

注意:@ts-ignore在有问题的行上方添加一个确实可以消除错误,但这并不能解决问题。

我试过删除 node_modules 并重新启动所有内容以确保它不是故障

它在 docker 镜像中运行

回答

对于validatordefaultprop声明中,Vue 文档规定 (1) 使用箭头函数,或 (2) 提供显式this参数:

警告

由于的设计限制在打字稿,当涉及到输入函数表达式的推论,你必须要小心validatordefault值对象和数组:

import { defineComponent, PropType } from 'vue'

interface Book {
  title: string
  year?: number
}

const Component = defineComponent({
  props: {
    bookA: {
      type: Object as PropType<Book>,
      // Make sure to use arrow functions
      default: () => ({
        title: 'Arrow Function Expression'
      }),
      validator: (book: Book) => !!book.title
    },
    bookB: {
      type: Object as PropType<Book>,
      // Or provide an explicit this parameter
      default(this: void) {
        return {
          title: 'Function Expression'
        }
      },
      validator(this: void, book: Book) {
        return !!book.title
      }
    }
  }
})

TypeScript 的首席架构师 Anders Hejlsberg 在GitHub 评论中解释了这个问题:

这是设计限制。类似于#38872。没有参数的 [n] 箭头函数不是上下文敏感的,但没有参数的函数表达式是上下文敏感的,因为隐式this参数。任何上下文敏感的东西都被排除在类型推断的第一阶段,这是确定我们将用于上下文类型参数的类型的阶段。因此,在原始示例中,当a属性的值是箭头函数时,我们在A为 的 a 参数分配上下文类型之前成功地进行了推断b。但是当值是一个函数表达式时,我们不做任何推断并且a参数被赋予 type unknown


原答案:

您的道具之一与 的预期签名不匹配PropOptions,这显然破坏了 中props参数的类型推断setup()。具体来说,由于某种原因,TypeScript 没有看到签名size.validator与类型匹配PropOptions.validator

有趣的是,如果更改validator为箭头函数,则类型推断props成功:

export default defineComponent({
  props: {
    size: {
      type: String,
      required: false,
      default: 'lg',
      //validator: function (value: string) { /*...*/ },
      validator: (value: string) => { /*...*/ },
    },
  }
})


以上是将道具传递到设置时,VueJS3CompositionAPI和TypeScript类型问题:类型上不存在属性“用户”的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>