프로젝트 도중 제네릭 관련해서 문제가 발생했다. 분명히 내 상식 안에서는 이 코드가 작동해야 하는데 작동하지 않았고, 이를 통해 제네릭에 대해서 공부하는 계기가 되었다.
바로 아래에 있는 코드에서 문제가 발생했다.
const initialSelectData: SelectedEventInfo = {
eventId: 0,
memo: '',
date: dayjs().format('YYYY.MM.DD'),
situation: '미납',
nickname: '',
amount: 0,
ground: '지각',
};
const func = <T extends SelectedEventInfo, K extends keyof T>(...arg: K[]) => {
const newObj: Partial<Record<K, T[K]>> = {};
arg.forEach((key) => {
if (key in initialSelectData) {
//Error: Type 'K' cannot be used to index type 'SelectedEventInfo'
newObj[key] = initialSelectData[key];
}
});
return newObj;
};
K는 SelectedEventInfo의 인덱스 타입
이 될 수 없다는 에러가 빵빵 터지고 있다. 😢
T는 SelectedEventInfo를 확장한 타입이고,
K는 T의 키값이니까 당연히 initialSelectData의 K인덱스는 존재해야 마땅하다고 생각했다.
위에는 내가 놓친 부분이 있었다. 바로 T는 SelectedEventInfo를 확장한 부분이라는 것이다.
확장을 했다는 것은 SelectedEventInfo 이 외에도 다른 값이 추가적으로 들어올 수 있다는 의미이다.
만약에 확장된 T에
🍎: 3
이란 값이 추가적으로 들어왔다고 생각해보자.
그렇게 되면 확장될 수 있는 T의 key값인 K에도🍎
값이 들어있어야 하는 게 당연하고,
당연하게도SelectedEventInfo[🍎]
는 존재하지 않는 값이기에 에러가 발생하는 것이었다.
SelectedEventInfo가 여러번 반복되어 보기 싫어서 단순히 제네릭을 사용하려고 했을 뿐인데,
지금까지 얼마나 생각없이 제네릭을 사용하는지 알 수 있었던 날이었다..
정확하게 사용하려면 아래와 같이 사용하면 될 거 같다.
const func = <K extends keyof SelectedEventInfo>(...arg: K[]) => {
const newObj: Partial<SelectedEventInfo> = {};
arg.forEach((key) => {
if (key in initialSelectData) {
newObj[key] = initialSelectData[key];
}
});
return newObj;
};