# 1383-Camelize

# 题目描述

实现 Camelize 类型: 将对象属性名从 蛇形命名(下划线命名) 转换为 小驼峰命名

Camelize<{
  some_prop: string;
  prop: { another_prop: string };
  array: [{ snake_case: string }];
}>;

// expected to be
// {
//   someProp: string,
//   prop: { anotherProp: string },
//   array: [{ snakeCase: string }]
// }

# 分析

这种题目之前也遇到不少,比如 114-CamelCase

只是这一题是上一题的升级版,需要对对象的属性值进行操作,而不是直接对字符操作。

借助 as 即可修改属性,套用 114-CamelCase 的解法即可。

type Camelize<T> = {
  [P in keyof T as CamelCase<P & string>]: T[P] extends {} // 递归处理对象属性
    ? Camelize<T[P]>
    : T[P];
};

但是上述解法在面对元组元素的时候,就会出现问题:

type cases = [
  Expect<
    Equal<
      Camelize<{
        some_prop: string;
        prop: { another_prop: string };
        // 不能正确处理元组类型
        array: [
          { snake_case: string },
          { another_element: { yet_another_prop: string } },
          { yet_another_element: string },
        ];
      }>,
      {
        someProp: string;
        prop: { anotherProp: string };
        array: [
          { snakeCase: string },
          { anotherElement: { yetAnotherProp: string } },
          { yetAnotherElement: string },
        ];
      }
    >
  >,
];

所以还需要对元组进行遍历,每一个元素都进行一次递归处理即可。

# 题解

// [114-CamelCase](/hard/114-CamelCase.md)
type CamelCaseF<
  S extends string,
  // 辅助字符,存储 _ 之前遇到的字符
  W extends string = '',
> = S extends `${infer F}${infer R}`
  ? // 如果是 _
    F extends '_'
    ? // 处理 _ 之前的的字符 W, 并递归剩余字符,重置 W
      `${Capitalize<Lowercase<`${W}`>>}${CamelCaseF<R>}`
    : // 否则,递归剩余字符,将 F 存储 W 中
      `${CamelCaseF<R, `${W}${F}`>}`
  : // 遍历结束,取出最后一次的字符进行处理
    Capitalize<Lowercase<`${W}`>>;

// 单独处理掉第一个字符的小写
type CamelCase<S extends string> = Uncapitalize<CamelCaseF<S>>;

type ObjCamelize<T> = {
  [P in keyof T as CamelCase<P & string>]: T[P] extends {}
    ? Camelize<T[P]>
    : T[P];
};

type TupleCamelize<T> =
  // 遍历元组
  T extends [infer F, ...infer R]
    ? // 每一个元素进行递归处理
      [Camelize<F>, ...Camelize<R>]
    : [];

type Camelize<T> =
  // 判断是不是元组
  T extends any[]
    ? // 元组则进行遍历,并递归处理每一个元素
      TupleCamelize<T>
    : // 否则执行对象属性的处理
      ObjCamelize<T>;

这里其实还缺失了对函数的判断,Function extends {} 是 true,如果是函数,则需要直接返回,而不是继续递归,不过用例中并没有,就不做过多讨论了。

# 知识点

  1. 均是以前的知识拼凑的,看起来确实复杂一点
Last Updated: 2023/5/16 06:00:28