简体   繁体   中英

How do you handle multiple types within same event emitter -Typescript

I am trying to create a function using typescript that checks for the "Enter" key press and then if the length of the event.target.value is greater than 0, go to a page with the value.This is in a nextjs app hence the router.push line. Code roughly looks like this:

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"
        );
      }
    }
  };

To trigger this function, Im using onKeyDown prop in input element, like this:

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

The challenge here is since Im using typescript, the e type can be a Keyboard event or a Change Event. If I use the | to provide both types, I get errors since typescript is confused which event type to reference. Is there any way I can create an interface or some custom type that leverages both event types (a keyboard event vs a change event)? This interface or custom type will also need to take into account the preventDefault void function as well.

Thanks

You can use a type guard to assert that the event is a specific one of the events in the union type before attempting to access properties that do not exist on both types in the union type.

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


The above could also be written as

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
  }
};

User-Defined Type Guards

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM