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

如何将任意{[k: string]: any}对象映射至TypeScript泛型Output类型

TypeScript 泛型函数映射API返回JSON到指定类型的解决方案

问题背景

现有一个返回Output泛型类型的函数,调用API得到JSON对象后,希望将其映射为指定的Output类型。示例代码如下:

function myFunc<Output>(): Promise<Output> {
  const apiRes: {[Key: string]: string} = getFromAPI()

  return apiRes as Output
}

直接使用类型断言会触发TypeScript类型不匹配报错,需要实现类型安全的属性映射逻辑,但不清楚如何获取泛型Output的属性及对应值类型。


解决方案

1. 基于泛型约束与类型守卫的验证映射

先通过Record<string, unknown>约束Output为对象类型,再用类型守卫验证API返回值结构是否符合目标类型:

function myFunc<Output extends Record<string, unknown>>(): Promise<Output> {
  const apiRes: Record<string, string> = getFromAPI();

  // 类型守卫:验证对象是否匹配Output结构
  function isOutput(obj: unknown): obj is Output {
    if (typeof obj !== 'object' || obj === null) return false;
    return (Object.keys(obj as Output) as Array<keyof Output>).every(key => key in obj);
  }

  const mappedResult = apiRes as unknown as Output;
  if (isOutput(mappedResult)) {
    return Promise.resolve(mappedResult);
  }
  throw new Error("API返回结果不符合目标类型结构");
}

2. 显式遍历泛型属性做类型转换

利用keyof Output获取目标类型的所有属性键,结合Output[Key]获取对应值类型,实现针对性的类型转换:

function myFunc<Output extends Record<string, unknown>>(): Promise<Output> {
  const apiRes: Record<string, string> = getFromAPI();
  const result = {} as Output;

  // 遍历目标类型的所有属性键
  (Object.keys(result) as Array<keyof Output>).forEach(key => {
    const apiValue = apiRes[String(key)];
    if (!apiValue) throw new Error(`API返回缺少属性:${String(key)}`);

    // 根据目标值类型做转换
    switch (typeof result[key]) {
      case 'number':
        (result[key] as unknown) = Number(apiValue);
        break;
      case 'boolean':
        (result[key] as unknown) = apiValue === 'true' || apiValue === '1';
        break;
      case 'string':
        (result[key] as unknown) = apiValue;
        break;
      default:
        throw new Error(`不支持转换为类型:${typeof result[key]}`);
    }
  });

  return Promise.resolve(result);
}

3. 传入自定义转换函数(最灵活)

让调用者提供转换逻辑,利用TypeScript的泛型推导确保类型安全:

function myFunc<Output>(transform: (apiRes: Record<string, string>) => Output): Promise<Output> {
  const apiRes: Record<string, string> = getFromAPI();
  return Promise.resolve(transform(apiRes));
}

// 调用示例
interface User {
  id: number;
  name: string;
  active: boolean;
}

myFunc(res => ({
  id: Number(res.id),
  name: res.name,
  active: res.active === 'true'
})).then(user => {
  // user类型自动推导为User,完全类型安全
});

关键知识点

  • keyof Output:获取泛型Output的所有属性键联合类型,比如Output为User时,结果是'id' | 'name' | 'active'。
  • Output[Key]:通过属性键Key获取Output对应的值类型,实现类型针对性转换。
  • Record<string, unknown>:约束泛型必须为对象类型,避免传入非对象类型导致逻辑错误。

内容的提问来源于stack exchange,提问作者Omar Tiamani

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.15 13:40:25