将道具传递给设置时的VueJS 3组合API和TypeScript类型问题:类型上不存在属性“用户”
Posted
技术标签:
【中文标题】将道具传递给设置时的VueJS 3组合API和TypeScript类型问题:类型上不存在属性“用户”【英文标题】:VueJS 3 Composition API and TypeScript type issue when passing props into setup: Property 'user' does not exist on type 【发布时间】:2021-09-05 12:03:19 【问题描述】:我正在努力找出我做错了什么让 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" 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 声明:
在 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 镜像中运行
【问题讨论】:
【参考方案1】:对于prop
声明中的validator
和default
,Vue docs 规定(1)使用箭头函数,或(2)提供显式this
参数:
警告
由于 TypeScript 中的 design limitation 在涉及函数表达式的类型推断时,您必须小心对象和数组的
validator
和default
值: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 comment 中解释了这个问题:
这是一个设计限制。类似于#38872。没有参数的 [n] 箭头函数不是上下文敏感的,但是没有参数的函数表达式是上下文敏感的,因为隐含的
this
参数。任何与上下文相关的内容都被排除在类型推断的第一阶段之外,该阶段确定我们将用于上下文类型参数的类型。因此,在原始示例中,当a
属性的值是箭头函数时,我们在将上下文类型分配给b
的a 参数之前成功地推断出A
。但是当值是一个函数表达式时,我们不做任何推断,a
参数被赋予类型unknown
。
原答案:
您的一个道具与PropOptions
的预期签名不匹配,这显然破坏了setup()
中props
参数的类型推断。具体来说,由于某种原因,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) => /*...*/ ,
,
)
【讨论】:
以上是关于将道具传递给设置时的VueJS 3组合API和TypeScript类型问题:类型上不存在属性“用户”的主要内容,如果未能解决你的问题,请参考以下文章
如何在 vuejs 中通过 <router-link /> 将道具传递给命名视图?
在VueJS 2中通过v-for中的道具将数据从父级传递给子级