{
buy: [ // 구매 목록
{ tradeDate: '2023-03-22T18:55:07', saleSn: '641acd4ea430e79103bdb95e', spid: 279228251, grade: 5, value: 13300000000 },
{ tradeDate: '2023-03-22T18:55:07', saleSn: '641acd4ea430e79103bdb95e', spid: 279228251, grade: 5, value: 13300000000 },
...
],
sell: [ // 판매 목록
{ tradeDate: '2023-03-22T18:55:07', saleSn: '641acd4ea430e79103bdb95e', spid: 279228251, grade: 5, value: 13300000000 },
{ tradeDate: '2023-03-22T18:55:07', saleSn: '641acd4ea430e79103bdb95e', spid: 279228251, grade: 5, value: 13300000000 },
...
],
}
// { "tradeDate": "2023-05-31T01:07:25",
// "saleSn": "64761f3cad134d6873034f84",
// "spid": 265204024,
// "grade": 1,
// "value": 499000000 }
interface TradeLogInfo {
tradeDate: string;
saleSn: string;
spid: number;
grade: number;
value: number;
}
const [tradeInfo, setTradeInfo] = useState<{ buy: TradeLogInfo[]; sell: TradeLogInfo[] } | null>(null);
여기서 , 특정 로직에 의해 sell , buy 라는 부분을 분리해서 따로 보여주고자 할 때 (초깃값은 buy)
tradeType이라는 상태를 새로 만들고, 여기에 buy 나 sell 이라는 값을 넣어서
대괄호 표기법을 이용하여 tradeInfo의 키에 접근하는 것이다
const [tradeInfo, setTradeInfo] = useState<{ buy: TradeLogInfo[]; sell: TradeLogInfo[] } | null>(null);
...
const [tradeType, setTradeType] = useState('buy');
// type inference 때문에 굳이 string으로 지정할 필요 x
// const [tradeType, setTradeType] = useState<string>('buy');
...
return (
<>
{tradeInfo[tradeType].map((i) => {...}}
</>
)
'string' 형식의 식을 '{ buy: TradeLogInfo[]; sell: TradeLogInfo[]; }' 인덱스 형식에 사용할 수 없으므로 요소에 암시적으로 'any' 형식이 있습니다.
'{ buy: TradeLogInfo[]; sell: TradeLogInfo[]; }' 형식에서 'string' 형식의 매개 변수가 포함된 인덱스 시그니처를 찾을 수 없습니다.ts(7053)
이 문제는 TS는 객체의 키를 컴파일 시점에 검증하기 때문에,
tradeType 변수의 값이 'buy'나 'sell'임을 알 수 없다
그러므로 TS는 tradeType이 잠재적으로 tradeInfo 객체의 유효하지 않은 키일 수 있다고 판단하므로 에러를 발생시키는 것이다
string 타입으로 지정해줘도 마찬가지이다
string 타입은 'buy'와 'sell' 뿐만 아니라 JavaScript에서 가능한 모든 문자열을 포함하므로
TypeScript는 tradeType이 tradeInfo의 키로 사용될 때 안전하다고 판단할 수 없다
간단한 예시로
tradeType이 "axvnjzklds"와 같은 값으로 설정될 경우
tradeInfo["axvnjzklds"]는 존재하지 않으므로, TypeScript는 이러한 가능성을 염두에 두고 에러를 발생시키는 것이다
결론부터 말하자면
초깃값은 buy로 보장을 하더라도,
추후 동적으로 어느 값으로 바뀔지 모르기 때문에 에러를 발생시키는 것이다
TS 는 정적으로 타입을 검사하기 때문에 코드를 실행하지 않고,
컴파일 시점 코드를 분석하여 타입 안정성을 검증한다
그 말은 useState의 초기값으로 'buy'를 넣었지만, tradeType의 값은 실행 시간에 변경될 수 있다는 것이며
예를 들어, 나중에 setTradeType 함수를 호출하여 tradeType의 값을
'anvlkqwelas' 같은 이상한 값으로 변경할 수 있게 된다
따라서 TypeScript는 tradeType이 초기에 'buy'였더라도 이후에 어떤 값이 될지 확신할 수 없기 때문에 사전에 에러를 발생시키는 것이다
TS 가 더 정확한 추론을 할 수 있게 하려면, useState에서 가능한 상태를 모두 지정해야 한다
따라서, tradeType이 무조건 'buy' 또는 'sell' 중 하나임을 TypeScript에게 알려줘야 한다
즉 , 아래 둘 중 하나의 방법으로 해결이 가능하다
const [tradeType, setTradeType] = useState<'buy' | 'sell'>('buy');
if (tradeType === 'buy' || tradeType === 'sell') {
console.log(tradeInfo![tradeType]);
}
// 어차피 string 타입
const [tradeType, setTradeType] = useState('buy');
// string 타입이지만 무조건 'buy' 아니면 'sell'을 보장
type buyOrSell = 'buy' | 'sell'
console.log(tradeInfo![tradeType as buyOrSell]);