You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 11:41:23