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

React+TypeScript项目中如何实现更简洁的API键映射器?

解决方案

下面提供两种无需引入第三方依赖的实现方案,你可以根据项目需求选择:

方案1:统一转换为驼峰格式(推荐,最符合前端编码习惯)

只需要在API响应拦截层做一次统一转换,后续所有组件都可以直接用驼峰格式的键访问,不需要再依赖Mapper对象。

// TS类型工具:把snake_case类型批量转成camelCase类型
type SnakeToCamel<S extends string> = S extends `${infer First}_${infer Rest}`
  ? `${Lowercase<First>}${Capitalize<SnakeToCamel<Rest>>}`
  : Lowercase<S>;

type SnakeToCamelObject<T> = {
  [K in keyof T as SnakeToCamel<string & K>]: T[K] extends object 
    ? SnakeToCamelObject<T[K]> 
    : T[K];
};

// 运行时转换函数,轻量无依赖
function snakeToCamel<T extends Record<string, any>>(obj: T): SnakeToCamelObject<T> {
  const result = {} as any;
  for (const [key, value] of Object.entries(obj)) {
    const camelKey = key.replace(/_([a-z])/g, (_, letter) => letter.toUpperCase());
    result[camelKey] = typeof value === 'object' && value !== null && !Array.isArray(value)
      ? snakeToCamel(value)
      : value;
  }
  return result;
}

在你封装的API请求逻辑里加入转换逻辑即可:

// 原始接口返回类型(按后端返回的snake_case定义)
interface RawAPIResult {
  hello_world: string;
  user_info: {
    user_id: number;
    user_name: string;
  }
}

// 请求函数示例
async function fetchData(): Promise<SnakeToCamelObject<RawAPIResult>> {
  const res = await fetch('/api/xxx');
  const rawData = await res.json() as RawAPIResult;
  return snakeToCamel(rawData);
}

组件内直接用驼峰键访问,有完整的类型提示:

const data = await fetchData();
const text = data.helloWorld; 
const userId = data.userInfo.userId;

方案2:不修改原始返回对象,仅简化访问逻辑

如果你不想改动运行时的对象结构,可以基于原有Mapper用Proxy做一层轻量访问代理:

// 原有Mapper保持不变
const Mapper = {
  HELLO_WORLD: 'hello_world',
} as const;

interface RawAPIResult {
  [Mapper.HELLO_WORLD]: string;
}

// 代理类型定义
type MappedResult<T, M extends Record<string, keyof T>> = {
  [K in keyof M as Lowercase<K>]: T[M[K]];
};

// 代理创建工具
function createMappedResult<T, M extends Record<string, keyof T>>(raw: T, mapper: M): MappedResult<T, M> {
  return new Proxy({}, {
    get(_, key: string) {
      const mapperKey = key.toUpperCase() as keyof M;
      return raw[mapper[mapperKey]];
    }
  }) as MappedResult<T, M>;
}

使用方式:

const rawResult: RawAPIResult = await fetch('/api/xxx').then(res => res.json());
const result = createMappedResult(rawResult, Mapper);

// 组件内直接用小写驼峰访问
const text = result.helloWorld; // 等价于rawResult[Mapper.HELLO_WORLD],有完整类型提示

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.09.27 06:45:04