В настоящее время я переношу приложение Nuxt с версии 2 на версию 3, а также добавляю TypeScript в стек. В одном из моих шаблонов компонентов я перебираю набор ключей неизвестных объектов, чтобы создать список входов радио или флажков.
<template
v-for = "(optionValue, optionKey) in options"
:key = "`filter-option-${optionKey}`"
>
<input
:id = "optionKey.toString()"
v-model = "selection"
class = "filter-options-input visually-hidden"
:value = "optionKey"
:name = "name"
:type = "type"
>
<label
:for = "optionKey.toString()"
:class = "['filter-options-label', `is-${type}`]"
>
{{ optionValue }}
</label>
</template>
Код создает необходимые поля, как и ожидалось, но я не могу исправить следующую ошибку TypeScript в атрибуте <input>s :value:
Литерал объекта не может иметь несколько свойств с одним и тем же именем. ц(1117)
Вот жалуется:
Определение типа для options выглядит так:
type Option = {
[key: string]: string;
}
Фактические данные будут выглядеть так:
{
"portrait":"Hochformat",
"landscape":"Querformat",
"square":"Quadratisch"
}
или вот так:
{
"akane-akane": "Akane, Akane",
"anita-staud": "Staud, Anita",
"anne-marie-chatelier": "Chatelier, Anne-Marie",
"anneli-schuetz": "Schütz, Anneli",
"annette-gundermann": "Gundermann, Annette",
"arno-mohr": "Mohr, Arno",
...
}
Что TypeScript хочет сказать мне здесь и как я могу исправить сообщение об ошибке?
Вот репродукция в Codesandbox: https://codesandbox.io/p/sandbox/agitated-mendeleev-ypytew?file=%2Fcomponents%2Finput-list.vue&selection=%5B%7B%22endColumn%22%3A14% 2C%22endLineNumber%22%3A34%2C%22startColumn%22%3A14%2C%22startLineNumber%22%3A34%7D%5D
Да, вы правы для флажка и радио, вам нужно значение, извините, я пропустил эту часть.
Но в вашем случае optionKey это объект, который, я думаю, вам нужно сделать optionKey.key вы пробовали это?
Спасибо @nicholasnet, как сказано, код действительно работает. Я использую здесь v-for, как описано для объектов (vuejs.org/guide/essentials/list.html#v-for-with-an-object), поэтому optionKey на самом деле просто ключ, а не сам объект. Мне просто интересно, почему TypeScript жалуется и как я могу это решить.






Проблема:
связано с неправильным вводом v-model как псевдонима InputHTMLAttributes.value. Согласно документам, v-model на
<input type = "checkbox">и<input type = "radio">используют свойствоchecked...
... который не имеет ничего общего со свойством value.
Сначала я подумал, что это исходит от nuxt (потому что это была единственная зависимость в песочнице, которую вы связали, и я не вижу того же в новом проекте vue), поэтому я открыл этот тикет в их репозитории.
Однако оказывается, что виновником неправильного ввода является Volar, расширение IDE, используемое Codesandbox (и, скорее всего, вашей IDE).
Если вы хотите продолжить это, не стесняйтесь поднимать вопрос с Volar в их репо.
Исправления:
v-bind:<input
:id = "optionKey.toString()"
v-model = "selection"
class = "filter-options-input visually-hidden"
v-bind = "{ value: optionKey, name, type }"
/>
<input
...
v-model = "selection"
...
:data-foo = "/* ts-ignore */"
:value = "optionKey"
...
/>
Спасибо @tao за ваш ответ. Вы правы, окончательный код в браузере действительно работает. Здесь просто TypeScript не устраивает, и я не понимаю, почему. Но нет ли лучшего способа, чем просто игнорировать его или создать отдельный шаблон?
Ах, спасибо за объяснение @tao! В этом есть смысл. Так что я должен каким-то образом сказать TypeScript, что это может быть только type = "radio" или type = "checkbox", но ничего больше, верно?
Да, это должно убрать ошибку. Какое точное правило вызывает ошибку? Вы увидите это при наведении на ошибку.
Это сообщение об ошибке: литерал объекта не может иметь несколько свойств с одинаковым именем. ц(1117)
(свойство) InputHTMLAttributes.value?: любое
Не могли бы вы создать codeandbox.io (или аналогичный)? Он должен иметь как минимум package.json и компонент, где вы это видите. + минимум для воспроизведения проблемы.
Вот репродукция в Codesandbox: codeandbox.io/p/sandbox/…
Привет @tao, большое спасибо за ваши усилия, подачу заявки и обновление вашего ответа с доступными исправлениями! Ваше объяснение действительно помогает лучше понять, в чем проблема. Отличная работа! Я нашел решение v-bind самым «элегантным» на данный момент. По какой-то странной причине это работает, только если я перемещаю v-model после директивы v-bind. Наоборот, я бы получил ошибку в директиве v-model. Но, в конце концов, вы правы, я использую Volar в VSCode, и отключение этого на самом деле не вариант, но я зарегистрирую проблему с vuejs/language-tools, как предложил Дэниел.
Сообщает о проблеме в языковых инструментах vue: github.com/vuejs/language-tools/issues/2399. Давайте посмотрим.
Как оказалось проблема была не в коде, а в моей IDE. Расширение Volar, которое я использую, имеет неточное определение типа реквизита для v-model.
Теперь это исправлено в vuejs/language-tools с версией 1.1.3 (2023/2/18).
Спасибо за ваш ответ, но поскольку я использую здесь радио и флажки, мне нужно установить значение, чтобы Vue знал, какое значение установлено, когда использование выбирает одно из них. Например, как описано здесь: vuejs.org/guide/essentials/forms.html#checkbox. В противном случае я бы просто получал «включено» в качестве значения для каждого ввода.