오늘 진행한 개발 내용 중, 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]]>;
현재 읽고 있는 책인 이펙티브 타입스크립트에서도 나오듯이, 타입 단언보다는 타입 선언을 사용 하는 것이 바람직하다고 하니, 해당 부분은 이 문서를 참고하여 고친 후에 따로 정리해 볼 예정이다.