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
相关产品推荐
相关产品推荐

