TypeScript中如何将泛型对象指定为函数返回类型?
TypeScript泛型表单数据解析函数类型报错解决方法
我正在编写一个TypeScript函数,它接收Request类型的参数,返回结构可变的对象。函数代码如下:
export async function getFormData<T>(req: Request): Promise<T> { let data = {} as T const formdata = await req.formData(); formdata.forEach((value, key) => { data[key] = value; // <- 此行报错 }); return data; }
我希望调用时通过指定泛型类型让返回值获得对应类型:
const res = await getFormData<myInterface>(req);
但TypeScript持续报错:
Element implicitly has an 'any' type because expression of type 'string' can't be used to index type 'unknown'.
No index signature with a parameter of type 'string' was found on type 'unknown'
简言之:如何编写一个调用时可指定返回对象类型的函数?此前参考过相关方案,但会导致所有类型变为'any',不符合需求。
问题根源
TypeScript无法确认泛型T支持字符串索引,同时FormData的value类型为FormDataEntryValue(仅包含string或File类型),直接赋值给T的属性会触发类型不匹配检查。
解决方案
方案一:约束泛型为兼容FormData的字符串索引类型
给泛型T添加约束,确保它是可通过字符串索引的对象,且属性值兼容FormDataEntryValue:
export async function getFormData<T extends Record<string, FormDataEntryValue>>(req: Request): Promise<T> { const data = {} as T; const formdata = await req.formData(); // 改用for...of遍历entries,提升类型推断友好度 for (const [key, value] of formdata.entries()) { data[key as keyof T] = value; } return data; }
说明:
T extends Record<string, FormDataEntryValue>强制T的结构为字符串索引对象,且属性值能接受FormData返回的value类型key as keyof T断言当前遍历的key属于T的属性键,解决索引类型不匹配问题
方案二:支持任意属性类型(需自行保证类型兼容)
如果你的目标接口myInterface包含非FormDataEntryValue类型的属性(如数字、布尔值),可以放宽泛型约束,同时添加类型断言:
export async function getFormData<T extends Record<string, unknown>>(req: Request): Promise<T> { const data = {} as T; const formdata = await req.formData(); for (const [key, value] of formdata.entries()) { // 可根据实际需求在这里添加类型转换逻辑,比如把字符串转数字 data[key as keyof T] = value as unknown as T[keyof T]; } return data; }
注意:这种方式需要你自行确保FormData中的值可以安全转换为T对应的属性类型,否则可能引发运行时错误。
调用示例
假设定义了如下接口:
interface myInterface { username: string; age: string; avatar: File; }
调用时直接指定泛型即可获得正确类型:
const res = await getFormData<myInterface>(req); // res将被TypeScript推断为myInterface类型
内容的提问来源于stack exchange,提问作者mizerable
相关产品推荐
相关产品推荐

