将道具传递到设置时,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 镜像中运行
回答
对于validator和default在prop声明中,Vue 文档规定 (1) 使用箭头函数,或 (2) 提供显式this参数:
警告
由于的设计限制在打字稿,当涉及到输入函数表达式的推论,你必须要小心
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 评论中解释了这个问题:
这是设计限制。类似于#38872。没有参数的 [n] 箭头函数不是上下文敏感的,但没有参数的函数表达式是上下文敏感的,因为隐式
this参数。任何上下文敏感的东西都被排除在类型推断的第一阶段,这是确定我们将用于上下文类型参数的类型的阶段。因此,在原始示例中,当a属性的值是箭头函数时,我们在A为 的 a 参数分配上下文类型之前成功地进行了推断b。但是当值是一个函数表达式时,我们不做任何推断并且a参数被赋予 typeunknown。
原答案:
您的道具之一与 的预期签名不匹配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) => { /*...*/ },
},
}
})