泛型函数组件报错:'string'无法赋值给类型'P'的参数
泛型Select组件类型报错问题解析
问题描述
我编写了两个泛型函数组件GenericSelect和GenericSelect2,二者都包含onSelect属性:
GenericSelect的onSelect类型为(value: unknown) => void,运行正常GenericSelect2的onSelect类型为(value: T) => void,但在将e.target.value传入onSelect时触发报错:'string'无法赋值给类型'T'的参数
报错原因
- HTML原生
select元素的e.target.value类型固定是string,而GenericSelect2的onSelect期望接收泛型类型T——TypeScript无法确认string和T一定兼容,因此抛出类型不匹配错误。 - 反观
GenericSelect,因为unknown是所有类型的父类型,string可以安全赋值给unknown,所以不会报错,但这种写法丢失了泛型的类型约束能力。
修复方案(保留(value: T) => void类型约束)
方案1:约束泛型范围+类型断言
如果你的业务场景中T始终是字符串或字符串字面量类型,可以给泛型添加范围约束,再通过类型断言明确值的类型:
type GenericSelect2Props<T extends string> = { onSelect: (value: T) => void; options: { label: string; value: T }[]; }; const GenericSelect2 = <T extends string>({ onSelect, options }: GenericSelect2Props<T>) => { const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => { onSelect(e.target.value as T); }; return ( <select onChange={handleChange}> {options.map((opt) => ( <option key={opt.value} value={opt.value}> {opt.label} </option> ))} </select> ); };
方案2:通过选项匹配获取精准类型
这种方式不需要断言,通过查找选中的选项来获取符合T类型的值,更安全:
type GenericSelect2Props<T> = { onSelect: (value: T) => void; options: { label: string; value: T }[]; }; const GenericSelect2 = <T>({ onSelect, options }: GenericSelect2Props<T>) => { const handleChange = (e: React.ChangeEvent<HTMLSelectElement>) => { const selectedOption = options.find(opt => String(opt.value) === e.target.value); if (selectedOption) { onSelect(selectedOption.value); } }; return ( <select onChange={handleChange}> {options.map((opt) => ( <option key={String(opt.value)} value={String(opt.value)}> {opt.label} </option> ))} </select> ); };
这里需要把option的value转为字符串,因为HTML的option仅支持字符串类型的value属性,通过String(opt.value)实现兼容,再通过查找匹配还原出原始的T类型值。
内容的提问来源于stack exchange,提问作者Tempura
相关产品推荐
相关产品推荐

