es-toolkit > toCamelCaseKeys

최정은·어제
1

오픈소스 기여

목록 보기
1/1

https://github.com/toss/es-toolkit/pull/1362

기존 타입


type CamelCase<S extends string> = S extends `${infer P1}_${infer P2}${infer P3}`
  ? `${Lowercase<P1>}${Uppercase<P2>}${CamelCase<P3>}`
  : Lowercase<S>;

type ToCamelCaseKeys<T> = T extends any[]
  ? Array<ToCamelCaseKeys<T[number]>>
  : T extends Record<string, any>
    ? { [K in keyof T as CamelCase<string & K>]: ToCamelCaseKeys<T[K]> }
    : T; 

type CamelCase를 보면 snake_case만 고려가 되어 있고 PascalCase는 고려가 되어 있지 않는 걸 확인할 수 있다.

변경된 점


type SnakeToCamel<S extends string> = S extends `${infer H}_${infer T}`
  ? `${Lowercase<H>}${Capitalize<SnakeToCamel<T>>}`
  : Lowercase<S>;

type PascalToCamel<S extends string> = S extends `${infer F}${infer R}` ? `${Lowercase<F>}${R}` : S;

/** If it's snake_case, apply the snake_case rule; otherwise, just lowercase the first letter (including PascalCase → camelCase). */
type AnyToCamel<S extends string> = S extends `${string}_${string}` ? SnakeToCamel<S> : PascalToCamel<S>;

type ToCamelCaseKeys<T> = T extends any[]
  ? Array<ToCamelCaseKeys<T[number]>>
  : T extends Record<string, any>
    ? { [K in keyof T as AnyToCamel<Extract<K, string>>]: ToCamelCaseKeys<T[K]> }
    : T;

PascalCase를 고려하도록 함.

배운점

  • infer 설명
    • infer조건부 타입(conditional type) 안에서 새로운 타입 변수를 선언할 때 사용함.

    • 보통 extends와 함께 쓰여서, 타입의 일부분을 추출(infer = 추론)하는 역할을 함.

    • 런타임 코드가 아니라 타입 레벨에서 "이 부분을 타입 변수로 잡아서 써라"라고 함.

      예시

      type GetFirstArg<T> = T extends (arg: infer U, ...args: any[]) => any ? U : never;
      
      type A = GetFirstArg<(x: number, y: string) => void>; // number
      type B = GetFirstArg<(x: boolean) => void>;           // boolean

      👉 함수 타입에서 첫 번째 인자의 타입을 U로 추론해내는 패턴.

  • Lowercase 설명
    • 타입스크립트가 제공하는 내장 유틸리티 타입 중 하나.

    • 문자열 리터럴 타입의 모든 문자를 소문자로 변환해줌.

    • 런타임 문자열이 아니라 타입 레벨에서만 작동한다는 게 포인트.

      예시

      type A = Lowercase<'HELLO'>;     // "hello"
      type B = Lowercase<'UserName'>;  // "username"
  • Capitalize 설명
    • 이것도 내장 유틸리티 타입.

    • 문자열 리터럴 타입의 첫 글자만 대문자로 바꿔줌. 나머지는 그대로 둠.

      예시

      type A = Capitalize<'hello'>;   // "Hello"
      type B = Capitalize<'userName'>; // "UserName"

0개의 댓글