IT,프로그래밍/better code

[자바스크립트, TS] camel case의 object key를 snake case로 바꾸기

개발을 진행하다 Hasura에 query의 결과값으로 받아오는 object의 key가 snake case인데

실제 개발 컨벤션은 camel case여서 코드내에서 query한 결과값을 insert할때 다시 넣어줘야 하는 번거로움이 있었다.

const originalSnake = {
  hello_world: "hihi",
  hi_there: "hi there",
};

const insertObject = {
  helloWorld: originalSnake.hello_world,
  hiThere: originalSnake.hi_there,
};
console.log(originalSnake);
console.log(insertObject);

/*
{ hello_world: 'hihi', hi_there: 'hi there' }
{ helloWorld: 'hihi', hiThere: 'hi there' }
*/

이게 1개,2개일떄는 괜찮지만 점점 코드의 늘어감에 따라 object의 value는 그대로 두되, key의 컨벤션만 변경을 하고 싶어졌다.

우선 기존의 originalSnake object에 타입이 없는데 타입을 넣어주도록 하겠다.

const originalSnake: { [key: string]: any } = {
  hello_world: "hihi",
  hi_there: "hi there",
};

const converted: { [key: string]: any } = {};

{ [key: string]: any } 에서 타입을 key : string으로 안하는 이유는 key : string을 하게되면

originalSnake는 key를 'key'밖에 사용할수가 없다. 하지만 우리는 string의 모든 키를 쓰고 싶은것이기에

[ key : string] 을 함으로써 [abc], [kimchi] 등등의 key를 쓸수있게 해주고 value는 any 로 주었다.

const originalSnake: { [key: string]: any } = {
  hello_world: "hihi",
  hi_there: "hi there",
};

const converted: { [key: string]: any } = {};

for (const prop in originalSnake) {
    if (Object.prototype.hasOwnProperty.call(originalSnake, prop)) {
    console.log(prop);
  }
}

/*
hello_world
hi_there
*/

반복문에서 Object.prototype.hasOwnProperty.call(originalSnake, prop) 를 체크를 하고 넘어가는 이유는

object내에 존재를 확정할수 있도록 하는 것이 eslint에서 권장하는 방법이기에 키가 존재하는지 반복문 중간에 if로 체크하는 것이다

 

해당 console.log에서 보이는것과 같이 정규식으로 해결할수 있지만, node.js개발자로서 npm에 검색을 해본결과 사용하기 적합한 2개의 모듈을 발견하였다.

 

https://www.npmjs.com/package/has (Object.prototype.hasOwnProperty.call의 숏컷)

https://www.npmjs.com/package/change-case (코드 컨벤션을 변환해주는 모듈)

 

이때 우리 has의 경우 github를 보면 js로만 제작이 되었기에 @types/has 모듈을 추가로 설치하여준다

이제 설치한 모듈을 적용시켜보자

import has from "has";
import { camelCase } from "change-case";

const originalSnake: { [key: string]: any } = {
  hello_world: "hihi",
  hi_there: "hi there",
};

const converted: { [key: string]: any } = {};

for (const prop in originalSnake) {
    if (has(originalSnake, prop)) {
    console.log(camelCase(prop));
  }
}

/*
3 import has from "has";
         ~~~

  node_modules/@types/has/index.d.ts:16:1
    16 export = hasOwnProperty;
       ~~~~~~~~~~~~~~~~~~~~~~~~
    This module is declared with using 'export =', and can only be used with a default import when using the 'esModuleInterop' flag.
*/

이때 has에서 오류가 나게 되는데 이문제는 tsconfig.json 파일에 설정을 해주면 된다

{
  "compilerOptions": {
    "module": "commonjs",
    "esModuleInterop": true
  }
}

tsconfig.json

그러면

helloWorld
hiThere

위와 같이 카멜케이스로 잘 변형된 로그가 찍히게 된다.

이제 남은건 바뀐 string을 key값으로 만들어주는일만 남았다.

for (const prop in originalSnake) {
  if (has(originalSnake, prop)) {
    converted[snakeCase(prop)] = originalSnake[prop];
  }
}
console.log(converted);

/*
{ hello_world: 'hihi', hi_there: 'hi there' }
**/

성공!