Reputation: 1728
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
Upvotes: 1
Views: 2849
Reputation: 20821
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
}
};
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
}
};
Upvotes: 3