Solid JS中如何为Setter参数使用泛型键适配表单输入?
解决SolidJS表单状态更新的TypeScript类型错误
问题根源
你遇到的类型错误是因为createSignal推断出的form状态类型是固定的{ username: string; password: string },没有允许任意字符串键的索引签名,导致Setter<{...}>无法兼容Setter<any>,且直接用[name]更新状态时TypeScript会判定为不安全操作。
解决方案
1. 定义带索引签名的表单类型
先扩展表单状态的类型,允许任意字符串键(值类型与已有字段保持一致,这里是string):
type FormState = { username: string; password: string; // 允许添加任意字符串键,值为string类型 [key: string]: string; };
2. 创建带明确类型的表单信号
用上面定义的FormState约束createSignal的类型,确保setForm的类型支持任意键更新:
const [form, setForm] = createSignal<FormState>({ username: '', password: '' });
3. 子组件的类型适配
给InputText子组件定义正确的props类型,避免使用any,保证类型安全:
type InputTextProps = { name: string; value: string; setForm: Setter<FormState>; }; function InputText({ name, value, setForm }: InputTextProps) { const handleChange = (e: Event) => { const target = e.target as HTMLInputElement; // 现在可以安全使用[name]更新表单状态 setForm(prev => ({ ...prev, [name]: target.value })); }; return <input type="text" name={name} value={value} onChange={handleChange} />; }
4. 父组件中使用子组件
直接传递类型匹配的setForm和对应字段值即可:
function LoginForm() { const [form, setForm] = createSignal<FormState>({ username: '', password: '' }); return ( <form> <InputText name="username" value={form().username} setForm={setForm} /> <InputText name="password" value={form().password} setForm={setForm} /> // 支持添加自定义字段,比如email <InputText name="email" value={form().email || ''} setForm={setForm} /> </form> ); }
更安全的可选方案(限制键为已有字段)
如果不需要支持任意新增字段,只想用[name]更新已有字段,可以用keyof约束name的类型,避免拼写错误:
type InputTextProps<T> = { name: keyof T; value: string; setForm: Setter<T>; }; function InputText<T extends Record<string, string>>({ name, value, setForm }: InputTextProps<T>) { const handleChange = (e: Event) => { const target = e.target as HTMLInputElement; setForm(prev => ({ ...prev, [name]: target.value })); }; return <input type="text" name={name as string} value={value} onChange={handleChange} />; }
内容的提问来源于stack exchange,提问作者RobKohr
相关产品推荐
相关产品推荐

