#typescript #vue.js #vuejs3 #quasar-framework #vue-composition-api
Вопрос:
Я изо всех сил пытаюсь понять , что я делаю неправильно, чтобы заставить TypeScript понять, что props.user
это тип UserInterface
, любые советы или указатели были бы удивительными
vue@3.1.1, typescript@4.2.2, quasar@2.0.0-rc.3. Это больше похоже на проблему с собственным VueJS или машинописным текстом, а не на что-либо связанное с Квазаром
Интерфейс пользователя для справки:
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; } amp; { 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 и перезапустить все, чтобы убедиться, что это не сбой
он работает в образе докера
Ответ №1:
Для 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, объясняет проблему в комментарии на GitHub:
Это ограничение конструкции. Похоже на #38872. Функция со стрелкой[n] без параметров не зависит от контекста, но выражение функции без параметров зависит от контекста из-за неявного
this
параметра. Все, что зависит от контекста, исключается из первой фазы вывода типов, которая является фазой, определяющей типы, которые мы будем использовать для контекстно типизированных параметров. Итак, в исходном примере, когда значениемa
свойства является функция со стрелкой, нам удается сделать вывод дляA
, прежде чем мы назначим контекстный тип параметруb
a . Но когда значение является выражением функции, мы не делаем никаких выводов, иa
параметру присваивается тип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) => { /*...*/ },
},
}
})