Задать вопрос
@IliaMal

Как подправить метод js reduce что бы не ругался TypeScript?

Здравствуйте.

Переезжаю на TypeScript, столкнулся с ошибкой, который не могу понять
Исходный js (преобразует инпуты из формы в массив):
const data = Array
        .from(form.querySelectorAll('input'))
        .reduce((acc, n) => ((acc[n.name] ||= []).push(n.value), acc), {});


Смысл этой функции в том что бы все инпуты в форме поместить в массив и отправить потом аяксом
Пример
<form action="/ajxa/" method="post" class="js-form form">
					<div class="form__wrap">
						<input type="tel" name="phone" value="+7(555)444-33-22">
					</div>
					<div class="form__wrap">
						<input type="email" name="email" class="is-valid"  value="random@ya.ru">
					</div>
					<div class="form__wrap">
						<input type="text" name="name" class="is-valid"  value="Иван">
					</div>
					<button type="submit" class="btn">Отправить</button>
				</form>

Из формы надо получить массив:
[
'phone': "+7(555)444-33-22",
'email': "random@ya.ru",
'name': "Иван",
]


В TypeScript я осилил до этого момента:
type NameInput = {
            name: string | number,
            value: string
        }

        const data = Array
            .from(doForm[i].querySelectorAll('input'))
            .reduce<string[]>((acc, n: NameInput) => ((acc[n.name] ||= []).push(n.value), acc), []);

Ошибка
Элемент неявно содержит тип any, так как выражение индекса не имеет тип number.

Я не могу понять в чем дело, я указал что тип ключа string | number что еще надо TypeScript?
63c849d139036576392516.png
  • Вопрос задан
  • 235 просмотров
Подписаться 1 Средний 5 комментариев
Решения вопроса 1
В JS/TS массив не может быть подобного вида:
[
    'phone': "+7(555)444-33-22",
    'email': "random@ya.ru",
    'name': "Иван",
]

Ну точнее, строго говоря, может, но это немного дичь. Я никого не знаю, кто так использовал бы массивы, да и TS на такое ругается всё равно. Понятно, для чего подобное может быть удобно в теории, но для этого давно придумали объекты и Map.

Так что может, вы все-таки имели в виду объект? Тогда можно что-то вроде этого сделать
const submitForm = (e: SubmitEvent) => {
  e.preventDefault();
  const form = e.currentTarget as HTMLFormElement;
  const data = Object.entries(form.elements).reduce<Record<string, unknown>>(
    (acc, [key, element]) => {
      if (isNaN(Number(key)) && 'value' in element) {
        acc[key] = element.value;
      }
      return acc;
    },
    {}
  );
  console.log(data);
};

const form = document.getElementById("form");
form?.addEventListener("submit", submitForm);


Впрочем, аналогично можно привести и к тому виду, который вы описали, лишь немного переделав.
Ответ написан
Пригласить эксперта
Ответы на вопрос 1
Krasnodar_etc
@Krasnodar_etc
fundraiseup
Если вы хотите иметь на выходе тип string[], почему не сделать просто acc.push(n.value) ?

Ошибка, если я правильно понимаю, простая:
n = { name: 'some name', value: 'val' }; // Исходя из типа NameInput, в n может попасть такое значение, например
acc[n.name] => acc['some name'] => не может у массива быть такого (строкового) индекса


Кажется, вам будет удобнее аккумулировать в объект, а не массив
Ответ написан
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы