오늘의 개발

In9_9yu·2023년 5월 3일
2

mobae

목록 보기
1/9

Q1. Object.entires 의 타입추론

오늘 진행한 개발 내용 중, BE에서 받은 내용을 FE에서 사용할 수 있도록 적절하게 바꾸는 작업이 필요했다.

const data = {
  control:3,
  power:2,
  weight:3
}

const statisticsPropertyMapper = {
  criteria: {
  	control:'컨트롤',
  	power:'파워',
  	weight:'무게'
  }
  ...
}

위와 같은 구조의 코드가 있다고 할 때, 만들고자 하는 객체 형태는 아래와 같았다.

const transformedData = [
  { name:'컨트롤', value:3, filled: '...'},
  { name:'파워', value:2, filled: '...'},
  { name:'무게', value:3, filled: '...'},
]

변환하는 코드 자체는 어렵지 않다.

const transformedData = Object.entries(data).map(([key,value])=>({
	name: statisticsPropertyMapper.criteria[key], // warning
    value,
    filled : ...                                         
}))

vscode로 코드를 살펴보면, 다음과 같은 오류가 발생한다.

string' 형식의 식을 '{ control: string; power: string; weight: string; }' 인덱스 형식에 사용할 수 없으므로 요소에 암시적으로 'any' 형식이 있습니다.
{ control: string; power: string; weight: string; }' 형식에서 'string' 형식의 매개 변수가 포함된 인덱스 시그니처를 찾을 수 없습니다.

map 함수에서 사용되는 매개변수 key를 단순히 string으로만 추론하고 있었던 것이 문제였다.

좀 더 정확하게 말하면, Object.entries가 반환하는 값이 [string, number][] 이다 보니 발생하는 문제이다.

아래 조금 이상한 예시를 보면, Object.entries가 반환하는 값의 타입 때문인 것이 더욱 확실해진다.

interface Item {
  name:'name' | 'age' | 'hobby';
  value:number
}

const items : Item [] = [
  {name:'name', value:10 },
  {name:'age', value:12 },
  {name:'hobby', value:14 },
]

// 아래 name의 타입은 'name' | 'age' | 'hobby' 로 추론된다.
const result = items.map(({name,value}) => ({
  name:name + 'a',
  value: value +1
}))

사실 gpt의 도움을 받아서, Object.entries의 결과를 타입단언을 통해 지정해주는 방식으로 임시 처방? 했다.

const data = {
  control:3,
  power:2,
  weight:3
}

const statisticsPropertyMapper = {
  criteria: {
  	control:'컨트롤',
  	power:'파워',
  	weight:'무게'
  }
  ...
}

const dataEntries = Object.entries(data) 
	as Array<[keyof typeof genders, (typeof genders)[keyof typeof genders]]>;

현재 읽고 있는 책인 이펙티브 타입스크립트에서도 나오듯이, 타입 단언보다는 타입 선언을 사용 하는 것이 바람직하다고 하니, 해당 부분은 이 문서를 참고하여 고친 후에 따로 정리해 볼 예정이다.

profile
FE 임니다

0개의 댓글