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

如何在TypeScript中实现对象键名深转换:snake_case与camelCase互转?

TypeScript 实现对象键名蛇形/驼峰深度转换

要实现带类型推导的深度转换,核心是利用TypeScript的递归泛型类型跟踪转换后的键名和结构,同时保留原函数的递归遍历逻辑。以下是完整实现:

1. 字符串转换类型定义

先定义蛇形转驼峰、驼峰转蛇形的字符串类型,用于推导转换后的键名:

// snake_case 转 camelCase
type SnakeToCamel<S extends string> = S extends `${infer P}_${infer R}`
  ? `${P}${Capitalize<SnakeToCamel<R>>}`
  : S;

// camelCase 转 snake_case
type CamelToSnake<S extends string> = S extends `${infer P}${infer R}`
  ? P extends Lowercase<P>
    ? `${P}${CamelToSnake<R>}`
    : `_${Lowercase<P>}${CamelToSnake<R>}`
  : S;

2. 递归对象/数组类型转换

基于上面的字符串类型,定义递归处理对象和数组的泛型类型:

// 深度将对象键名从 snake_case 转为 camelCase
type CamelCaseKeys<T> = T extends Array<infer U>
  ? Array<CamelCaseKeys<U>>
  : T extends object
  ? {
      [K in keyof T as SnakeToCamel<Extract<K, string>>]: CamelCaseKeys<T[K]>
    }
  : T;

// 深度将对象键名从 camelCase 转为 snake_case
type SnakeCaseKeys<T> = T extends Array<infer U>
  ? Array<SnakeCaseKeys<U>>
  : T extends object
  ? {
      [K in keyof T as CamelToSnake<Extract<K, string>>]: SnakeCaseKeys<T[K]>
    }
  : T;

3. 辅助工具函数

实现判断普通对象的类型守卫,以及字符串格式转换函数:

// 判断是否为普通对象(排除数组、null、内置对象等)
function isPlainObject(value: unknown): value is Record<string, unknown> {
  return typeof value === 'object' && value !== null && Object.prototype.toString.call(value) === '[object Object]';
}

// 字符串 snake_case 转 camelCase
function camelCase(str: string): string {
  return str.replace(/_([a-z])/g, (_, char) => char.toUpperCase());
}

// 字符串 camelCase 转 snake_case
function snakeCase(str: string): string {
  return str.replace(/([A-Z])/g, '_$1').toLowerCase();
}

4. 核心转换函数

结合类型定义和工具函数,实现带类型推导的深度转换函数:

// 深度转换对象键名为 camelCase
function keyToCamelCase<T>(obj: T): CamelCaseKeys<T> {
  if (Array.isArray(obj)) {
    return obj.map(item => keyToCamelCase(item)) as CamelCaseKeys<T>;
  }

  if (!isPlainObject(obj)) {
    return obj as CamelCaseKeys<T>;
  }

  const newObj = {} as CamelCaseKeys<T>;

  Object.entries(obj).forEach(([key, value]) => {
    const camelKey = camelCase(key) as keyof CamelCaseKeys<T>;
    newObj[camelKey] = keyToCamelCase(value);
  });

  return newObj;
}

// 深度转换对象键名为 snake_case
function keyToSnakeCase<T>(obj: T): SnakeCaseKeys<T> {
  if (Array.isArray(obj)) {
    return obj.map(item => keyToSnakeCase(item)) as SnakeCaseKeys<T>;
  }

  if (!isPlainObject(obj)) {
    return obj as SnakeCaseKeys<T>;
  }

  const newObj = {} as SnakeCaseKeys<T>;

  Object.entries(obj).forEach(([key, value]) => {
    const snakeKey = snakeCase(key) as keyof SnakeCaseKeys<T>;
    newObj[snakeKey] = keyToSnakeCase(value);
  });

  return newObj;
}

示例使用

// 定义蛇形键的对象类型
interface SnakeCaseUser {
  user_name: string;
  user_age: number;
  user_address: {
    street_name: string;
    zip_code: string;
  };
  favorite_colors: string[];
}

// 蛇形键对象实例
const snakeUser: SnakeCaseUser = {
  user_name: 'Alice',
  user_age: 28,
  user_address: {
    street_name: 'Oak Ave',
    zip_code: '67890'
  },
  favorite_colors: ['purple', 'yellow']
};

// 转换为驼峰键对象,类型自动推导
const camelUser = keyToCamelCase(snakeUser);
// camelUser 的类型为:
// {
//   userName: string;
//   userAge: number;
//   userAddress: {
//     streetName: string;
//     zipCode: string;
//   };
//   favoriteColors: string[];
// }

// 转换回蛇形键对象,类型匹配原定义
const convertedBack = keyToSnakeCase(camelUser);
// convertedBack 类型为 SnakeCaseUser

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.26 17:42:06