I have an input that looks like this:
<input
type="text"
value={form().username}
onInput={(e) => handleInput(e)}
/>
And typescript suggests that e
is this type:
(parameter) e: InputEvent & {
currentTarget: HTMLInputElement;
target: Element;
}
If I create handleInput using that, using the name and value don't show up as part of the type definition, so I add them:
const handleInput = (e: InputEvent & {
currentTarget: HTMLInputElement;
target: Element & { name: string; value: string; };
}) => {
setForm({
...form(),
[e.target.name]: e.target.value,
});
}
However this makes my e
highlighted on the input textbox as an error:
Argument of type 'InputEvent & { currentTarget: HTMLInputElement; target: Element; }' is not assignable to parameter of type 'InputEvent & { currentTarget: HTMLInputElement; target: Element & { name: string; value: string; }; }'.
Type 'InputEvent & { currentTarget: HTMLInputElement; target: Element; }' is not assignable to type '{ currentTarget: HTMLInputElement; target: Element & { name: string; value: string; }; }'.
Types of property 'target' are incompatible.
Type 'EventTarget & Element' is not assignable to type 'Element & { name: string; value: string; }'.
Type 'EventTarget & Element' is missing the following properties from type '{ name: string; value: string; }': name, value
How can I fix this incompatibility as name and value are valid parts of the event target type.
The correct event type of an input event is as follows:
import { JSX } from "solid-js";
export const App = () => {
const handleInput: JSX.EventHandlerUnion<HTMLInputElement, InputEvent> = (event) => {
// currentTarget: EventTarget & HTMLInputElement
console.log(event.currentTarget.value);
}
return (
<input onInput={handleInput} />
);
};
Annotating the event directly does not work because the typeof currentTarget
is Element or null
but we know for sure its Element:
const handler = (event: InputEvent) => {
// Property 'value' does not exist on type 'EventTarget'
console.log(event.currentTarget.value);
}
If you don't want to use the union type, alternative could be:
const handler: JSX.EventHandler<HTMLInputElement, InputEvent> = (event) => {
// currentTarget: EventTarget & HTMLInputElement
console.log(event.currentTarget.value);
}
PS: You have an unnecessary callback that does nothing other than passing the value to the actual callback:
<input onInput={(e) => handleInput(e)} />
If I remember correctly React uses this syntax to fix some of its quirks, at least in its early days. In Solid it serves no purpose.
This sytax might be useful when you need to pass extra values like index number along with the event, (e) => handleInput(index, event)
when attaching the same handler to multiple items but better option would be partial application:
const handleInput = (index: number) => (event) => {
console.log(index);
}
<input onInput={handleInput(index)} />