React+TypeScript泛型输入Hook开发中的TS类型错误求助
useInput Hook Let's break down why you're hitting that "parameter 'e' implicitly has an 'any' type" error and fix it properly—plus we'll address a hidden type mismatch issue you might run into with number inputs.
The Root of the Problem
Your onChange callback's e parameter doesn't have an explicit type, and TypeScript can't infer it automatically. Even when you typed the bind object as any or a generic object, TypeScript still checks the internal code of the hook for type safety. Also, there's a hidden issue: when T is number, e.target.value is always a string (HTML input values are strings by default), so assigning it directly to a number state will cause a type mismatch.
Step-by-Step Fix
Here's the revised version of your useInput hook with proper typing and type handling:
import { useState, ChangeEvent } from "react"; export function useInput<T>(initialValue: T): [ T, { value: T extends number ? string : T; onChange: (e: ChangeEvent<HTMLInputElement>) => void; }, () => void ] { const [value, setValue] = useState<T>(initialValue); const reset = () => { setValue(initialValue); }; const bind = { // For number inputs, convert state number to string to match input's expected value type value: typeof value === "number" ? value.toString() : value, onChange: (e: ChangeEvent<HTMLInputElement>) => { const inputValue = e.target.value; // Convert input string back to the correct state type let parsedValue: T; if (typeof initialValue === "number") { parsedValue = parseFloat(inputValue) as T; } else { parsedValue = inputValue as T; } setValue(parsedValue); } }; return [value, bind, reset]; }
Key Changes Explained
- Typed Event Parameter: We explicitly type
easReact.ChangeEvent<HTMLInputElement>, which tells TypeScript exactly what kind of event we're dealing with—no more implicitany. - Input Value Type Alignment: HTML inputs always expect a string value, so for number states, we convert the number to a string when passing it to the
bind.valueproperty. This avoids type errors in your JSX. - State Type Conversion: When updating the state, we convert the input string back to the correct type (number or string) based on the initial value's type. This ensures the state stays aligned with the generic
Ttype. - Explicit Return Type: We replaced
anywith a precise type for thebindobject, so your component will get proper TypeScript intellisense when usingbindTextorbindAmount.
Using the Fixed Hook
Your component code stays almost the same—no changes needed there! TypeScript will now correctly infer all types without errors, and your number input will handle conversions between string (input value) and number (state) automatically.
Bonus: Strict Type Safety (Optional)
If you want even stricter type checking (to prevent passing non-string/non-number types), you can restrict the generic T to only valid input types:
export function useInput<T extends string | number>(initialValue: T): [ // ... rest of the type definition stays the same ] { // ... hook implementation stays the same }
This way, TypeScript will throw an error if someone tries to use the hook with a boolean or object type, which doesn't make sense for input elements.
内容的提问来源于stack exchange,提问作者Surya Bhusal

