将道具传递到设置时,VueJS 3 Composition API 和 TypeScript 类型问题:类型上不存在属性“用户" [英] VueJS 3 Composition API and TypeScript type issue when passing props into setup: Property 'user' does not exist on type

查看:123
本文介绍了将道具传递到设置时,VueJS 3 Composition API 和 TypeScript 类型问题:类型上不存在属性“用户"的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在努力找出我做错了什么让 TypeScript 理解 props.userUserInterface 类型,任何建议或指针都会很棒

I am struggling to work out what I am doing wrong to get TypeScript to understand that props.user is of type UserInterface, any advice or pointers would be amazing

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

vue@3.1.1, typescript@4.2.2, quasar@2.0.0-rc.3. This feels more like a native VueJS or TypeScript issue, rather than anything to do with 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" style="outline: 2px solid #ffffff">
    {{ 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 声明:

VueJS 3 documentation https://v3.vuejs.org/guide/typescript-support.html#using-with-composition-api states:

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

On setup() function, you don't need to pass a typing to props parameter as it will infer types from props component option.

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

However, i keep getting a complication error, and i am not sure what i am missing

结果:

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 确实消除了错误,但这并不能解决问题.

Notes: adding a @ts-ignore above the line in question does remove the error, but that's not solving the issue.

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

I've tried deleting node_modules and restarting everything to ensure its not a glitch

它在 docker 镜像中运行

its running in a docker image

推荐答案

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

For validator and default in the prop declarations, the Vue docs prescribe either (1) using an arrow function, or (2) provide an explicit this parameter:

由于 TypeScript 中的设计限制,当涉及到函数的类型推断时表达式,您必须注意对象和数组的 validatordefault 值:

WARNING

Because of a design limitation in TypeScript when it comes to type inference of function expressions, you have to be careful with validator and default values for objects and arrays:

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 评论中解释了这个问题:

Anders Hejlsberg, lead architect of TypeScript, explains the issue in a GitHub comment:

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

This is a design limitation. Similar to #38872. A[n] arrow function with no parameters is not context sensitive, but a function expression with no parameters is context sensitive because of the implicit this parameter. Anything that is context sensitive is excluded from the first phase of type inference, which is the phase that determines the types we'll use for contextually typed parameters. So, in the original example, when the value for the a property is an arrow function, we succeed in making an inference for A before we assign a contextual type to the a parameter of b. But when the value is a function expression, we make no inferences and the a parameter is given type unknown.


原答案:

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

One of your props doesn't match the expected signature of PropOptions, which apparently breaks the type inference for the props argument in setup(). Specifically, TypeScript doesn't see that the signature of size.validator matches up with the type of PropOptions.validator for some reason.

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

Interestingly, if you change validator to an arrow function, the type inference for props succeeds:

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

这篇关于将道具传递到设置时,VueJS 3 Composition API 和 TypeScript 类型问题:类型上不存在属性“用户"的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆