타입스크립트의 keyof와 typeof

Sheryl Yun·2022년 10월 3일
0

타입스크립트

목록 보기
1/11
post-thumbnail

최근에 진행 중인 Effitizer 프로젝트에서 기존에 작성된 코드를 분석하던 중에 as keyof typeof라는 표현을 발견했다. 작성하신 개발자 분에게 직접 여쭤보고 다음과 같은 내용을 알게 되었다.

문제 파악

기존 코드는 다음과 같은 형태였다.
소셜 로그인을 하기 위한 버튼을 렌더링하는 로그인 페이지 컴포넌트이다.

const providerInfo = {
  google: { name: 'Google', Icon: GoogleIcon },
  kakao: { name: '카카오', Icon: KakaoIcon },
  naver: { name: '네이버', Icon: NaverIcon },
};

...

const { name, Icon } = providerInfo[provider.id as keyof typeof providerInfo];

여기서 as keyof typeof 부분이 궁금했다.

우선 as keyof typeof providerInfo 부분을 지우면 providerInfo[provider.id]에 다음과 같은 에러가 발생한다.

Element implicitly has an 'any' type because expression of type 'LiteralUnion<BuiltInProviderType, string>' can't be used to index type '{ google: { name: string; Icon: (props: SVGProps) => Element; }; kakao: { name: string; Icon: (props: SVGProps) => Element; }; naver: { ...; }; }'.

이 문제를 해결하려면 providerInfo 객체의 '키'인 provider.id의 타입을 지정해주어야 했다.

키워드를 사용한 타입 지정

as는 타입 단언에 쓰이는 키워드이다.
keyof'(객체의) 키의 타입을 정한다'는 뜻이다.
typeof는 자바스크립트에서도 사용하는 '~의 타입'을 알려주는 키워드이다.

즉, as keyof typeof providerInfo 부분을 한 단어씩 해석하면

providerInfo 객체의 타입은 typeof providerInfo로 알아내고, 앞에 keyof를 붙이면 providerInfo 객체의 '키'의 타입으로 provider.id의 타입을 '단언'해줘('as')

라는 뜻이 된다.

이렇게 하면 컴포넌트 상단에 'type ProviderInfo ~' 또는 'interface ProviderInfo ~' 하는 식으로 명시적으로 지정하지 않고도 키워드를 통해 타입을 '서술적으로' 지정할 수 있게 된다.

코드 리팩토링

as keyof typeof가 가독성이 좋지 않을 것 같으면 다음과 같이 리팩토링이 가능하다.

const providerInfo = {
google: { name: 'Google', Icon: GoogleIcon },
kakao: { name: '카카오', Icon: KakaoIcon },
naver: { name: '네이버', Icon: NaverIcon },
};

type ProviderInfoKey = keyof typeof providerInfo;

...

const { name, Icon } = providerInfo[provider.id as ProviderInfoKey];
profile
데이터 분석가 준비 중입니다 (티스토리에 기록: https://cherylog.tistory.com/)

0개의 댓글