Как вы обрабатываете несколько типов в одном эмиттере событий - Typescript

Я пытаюсь создать функцию, используя машинописный текст, который проверяет нажатие клавиши Enter, а затем, если длина event.target.value больше 0, перейдите на страницу со значением. Это приложение nextjs, отсюда и строка router.push. Код примерно выглядит так:

const goToSearch = (e: React.KeyboardEvent<HTMLInputElement> | React.ChangeEvent<HTMLInputElement>) => {
    if (e.key === "Enter") {
      e.preventDefault();

      if (e.target.value.length > 0) {
        router.push(
          { pathname: "/Search", query: { searchVal: e.target.value } },
          "/Search"
        );
      }
    }
  };

Чтобы вызвать эту функцию, я использую реквизит onKeyDown в элементе ввода, например:

  <input
    type="search"
    className="form-control border border-white"
    placeholder="Search"
    aria-label="Search"
    onKeyDown={goToSearch}
  />

Проблема здесь в том, что, поскольку я использую машинописный текст, тип e может быть событием клавиатуры или событием изменения. Если я использую | чтобы предоставить оба типа, я получаю ошибки, так как машинописный текст не понимает, на какой тип события ссылаться. Можно ли каким-либо образом создать интерфейс или какой-либо пользовательский тип, который использует оба типа событий (событие клавиатуры и событие изменения)? Этот интерфейс или пользовательский тип также должны учитывать функцию void preventDefault.

Спасибо


person Ray    schedule 18.02.2021    source источник
comment
Посмотрите на охранники типов typescriptlang.org/ документы/руководство/   -  person ksav    schedule 18.02.2021


Ответы (1)


Вы можете использовать защиту типа, чтобы подтвердить, что событие является определенным событием в типе объединения, прежде чем пытаться получить доступ к свойствам, которые не существуют в обоих типах в типе объединения.

const goToSearch = (e: React.KeyboardEvent<HTMLInputElement> | 
React.ChangeEvent<HTMLInputElement>) => {
  const {key} = (e as React.KeyboardEvent<HTMLInputElement>)
  const {target} = (e as React.ChangeEvent<HTMLInputElement>)
  if (key === "Enter") {
    e.preventDefault();
  }
  if (target.value.length > 0) {
    // change route
  }
};

TS Playground


Вышеупомянутое также может быть записано как

const goToSearch = (e: React.KeyboardEvent<HTMLInputElement> | React.ChangeEvent<HTMLInputElement>) => {
  if ((e as React.KeyboardEvent<HTMLInputElement>) && (e as React.KeyboardEvent<HTMLInputElement>).key === "Enter") {
    e.preventDefault();
  }

  if ((e as React.ChangeEvent<HTMLInputElement>) && (e as React.ChangeEvent<HTMLInputElement>).target.value.length > 0) {
    // change route
  }
};

Определяемые пользователем типы защиты

person ksav    schedule 18.02.2021
comment
Это сработало. Можете ли вы объяснить, как вы пришли к этому решению, просто для моего понимания. Вы создали две деконструированные переменные из объекта события и установили их типы специально для каждого типа, указанного в параметре? Теперь, когда они разделены и связаны с определенной переменной, они избегают путаницы с типами? - person Ray; 18.02.2021
comment
Я прочитал обсуждения по этому вопросу, прежде чем придумать этот ответ. stackoverflow.com/questions/44321326/ - person ksav; 19.02.2021
comment
Ваше понимание правильное. Слово as в машинописном тексте утверждает переменную как один из возможных типов. - person ksav; 19.02.2021