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

如何实现可从对象转换函数自动推断类型的TypeScript泛型函数

实现精准类型推断的getSurveyData泛型函数

需求是实现getSurveyData函数,根据输入对象的结构(顶层值支持string/object/boolean/number),精准推断返回值的具体类型,而非当前宽泛的{ [x: string]: string | boolean | number; }。

输入示例1

const MOCK_DATA = {
  role: {
    option: 'Founder / CEO',
    text: '',
  },
  content: {
    option: 'Marketing videos',
    text: '',
  },
};

getSurveyData(MOCK_DATA)
// 返回类型应为:
// {
//   role: string;
//   content: string;
// }

输入示例2

const MOCK_DATA2 = {
  position: {
    option: ['Founder / CEO', 'Developer'],
    text: '',
  },
  termsConsent: true,
};

getSurveyData(MOCK_DATA2)
// 返回类型应为:
// {
//   position: string;
//   termsConsent: boolean;
// }

原有代码(类型推断不精准)

type FormValues = {
  [key: string]:
    | {
        option: string | string[];
        text: string;
      }
    | boolean
    | string
    | number
};

export const getSurveyData = (formValues: FormValues) => {

  return Object.entries(formValues).reduce(
    (
      prev: {
        [key: string]: string | boolean | number;
      },
      [key, data],
    ) => {
      let value: string | boolean | number = '';

      if (data instanceof Object) {

        if (Array.isArray(data.option)) {
          value = data.option.join(', ');

        } else {
          value = data.option;
        }
      }

      if (typeof data === 'boolean' || typeof data === 'string' || typeof data === 'number') {
        value = data;
      }

      return { ...prev, [key]: value };
    },
    {},
  );
};

修改后的泛型实现

要实现精准类型推断,需要使用泛型结合条件类型来映射输入类型到输出类型:

// 定义单个字段的输出类型映射
type SurveyFieldOutput<T> = 
  T extends { option: infer O } 
    ? O extends string[] 
      ? string 
      : O extends string 
        ? string 
        : never
    : T extends boolean | string | number 
      ? T 
      : never;

// 定义整个对象的输出类型映射
type SurveyDataOutput<T> = {
  [K in keyof T]: SurveyFieldOutput<T[K]>;
};

export const getSurveyData = <T extends Record<string, any>>(formValues: T): SurveyDataOutput<T> => {
  return Object.entries(formValues).reduce((prev, [key, data]) => {
    let value: SurveyFieldOutput<typeof data>;

    // 处理带option的对象类型
    if (typeof data === 'object' && data !== null && 'option' in data) {
      if (Array.isArray(data.option)) {
        value = data.option.join(', ') as SurveyFieldOutput<typeof data>;
      } else {
        value = data.option as SurveyFieldOutput<typeof data>;
      }
    } 
    // 处理基础类型
    else if (typeof data === 'boolean' || typeof data === 'string' || typeof data === 'number') {
      value = data as SurveyFieldOutput<typeof data>;
    } 
    // 兜底(根据需求可调整)
    else {
      value = '' as SurveyFieldOutput<typeof data>;
    }

    return { ...prev, [key]: value };
  }, {} as SurveyDataOutput<T>);
};

关键说明

  1. 泛型参数T:捕获输入对象的具体结构,替代原有的宽泛FormValues类型,保留每个字段的精确类型信息。
  2. 条件类型SurveyFieldOutput:
    • 若输入是带option的对象,根据option的类型(数组或字符串),输出都映射为string(因为数组会被join转为字符串)。
    • 若输入是基础类型(boolean/string/number),直接保留原类型。
  3. 映射类型SurveyDataOutput:遍历输入对象的所有键,将每个字段的类型通过SurveyFieldOutput转换为输出类型,构建最终的返回对象类型。
  4. 类型断言:在reduce中使用类型断言确保TS识别prev和value的正确类型,避免类型不兼容报错。

验证效果

使用示例1的MOCK_DATA调用getSurveyData,TS会推断返回类型为{ role: string; content: string; };使用示例2的MOCK_DATA2则会推断为{ position: string; termsConsent: boolean; },完全符合需求。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.24 18:44:52