keyof typeof 객체 키 바로 가져오기
안전한 타입스크립트
😵 들어가며
지난 게시글에서 vite 환경에서 svg를 리액트 노드 컴포넌트로 가져오는 법을 포스팅했었다. 그리고 오늘은 이어서, 가지고 온 컴포넌트를 Icon 컴포넌트 하나로 관리한 코드를 공유해보려 한다.
전체 코드
import Delete from '../icons/svg/delete.svg?react';
import Loading from '../icons/svg/loading.svg?react';
import Note from '../icons/svg/note.svg?react';
import Seed from '../icons/svg/seed.svg?react';
import Down from '../icons/svg/triangle-down.svg?react';
import Up from '../icons/svg/triangle-up.svg?react';
export const icons = {
Loading,
Delete,
Note,
Up,
Down,
Seed,
};
export type IconNameType = keyof typeof icons;
interface IconProps {
size?: 'xs' | 'sm' | 'md' | 'lg' | 'xl' | 'xxl';
color?: 'primary' | 'secondary' | 'danger' | 'white';
name: IconNameType;
onClick?: (e: React.MouseEvent<HTMLDivElement>) => void;
}
const Icon = ({ size = 'sm', color = 'primary', name, onClick }: IconProps) => {
const IconElement = icons[name];
const sizeMap = {
xs: 12,
sm: 16,
md: 24,
lg: 32,
xl: 48,
xxl: 60,
};
const colorMap = {
primary: '#1677FF',
secondary: '#bfbfbf',
danger: '#ff4d4f',
white: '#ffffff',
};
return (
<div
style=
onClick={onClick}>
<IconElement fill={colorMap[color]} />
</div>
);
};
export default Icon;
구조 설정
위의 코드를 보면 알 수 있듯, div 라는 부모 태그 내부에 icon 태그로 구성하였다. 그리고 부모 태그에 스타일을 주었는데 해당 사이즈와 컬러를 자식인 svg 가 받을 수 있도록 svg 파일을 수정해주어야한다. 아래 svg 파일에서 width, height을 각 100%로 수정하고 색상이 반영되어야할 부분을 current 혹은 currentColor로 변경해준다.
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 200 200" width="100%" height="100%">
<circle fill="current" stroke="current" stroke-width="15" r="15" cx="40" cy="100">
<animate attributeName="opacity" calcMode="spline" dur="2" values="1;0;1;" keySplines=".5 0 .5 1;.5 0 .5 1" repeatCount="indefinite" begin="-.4"></animate>
</circle>
</svg>
icon 자식 요소 갈아끼우기
아이콘을 하나하나 만드는 것 이라면 <div><Loading /></div>
식으로 썻을텐데, 나는 현재의 Loading 컴포넌트를 as 패턴 마냥 이름만 받아 갈아치우게 할 것이다.
import Delete from '../icons/svg/delete.svg?react';
import Loading from '../icons/svg/loading.svg?react';
export const icons = {
Loading,
Delete,
};
export type IconNameType = keyof typeof icons;
불러온 svg 컴포넌트를 우선 icons 라는 객체에 담는다. 그리고 중요한건 바로 이부분 export type IconNameType = keyof typeof icons;
keyof typeof를 사용하면 객체의 키를 타입으로 추출할 수 있다.
따로 또 같이 뜯어보자.
typeof : 각 키에 할당된 값의 타입을 가져온다.
const user = {
id: 1,
name: 'Alice',
age: 25,
};
type UserType = typeof user;
// UserType = { id: number; name: string; age: number; }
keyof : 객체 타입의 키를 문자열 타입으로 반환한다.
type UserKeys = keyof UserType;
// UserKeys = 'id' | 'name' | 'age'
keyof typeof : 합쳐서 객체의 키를 문자열 타입으로 반환한다.
const user = { id: 1, name: 'Alice', age: 25, }; type UserKeys = keyof typeof user;
// UserKeys = 'id' | 'name' | 'age'
이러한 속성을 이용해 Import 한 svg 들을 아이콘을 객체에 담고 타입으로 만들어주었다. 그리고 사용시에는 객체의 키를 가져오는 코드를 사용한다.
export type IconNameType = keyof typeof icons;
const Icon = (name: IconNameType) => {
// 객체의 키를 가져옴
const IconElement = icons[name];
return (
<div>
<IconElement/>
</div>
);
};
이렇게 하면 name에 따라 내부 자식 컴포넌트가 바뀌는 구조가 된다!
마무리
해당 문법을 사용하면서 키값을 타입으로 하기 때문에 굳이 다시 타입을 만들어줄 필요가 없었고, 잘못된 값이 사용될 가능성을 배제할 수 있었다. 또한 가독성을 높이는데 유용했고 나의 프로젝트 중 생각보다 많은 코드에 썼던 걸 확인했다. 잘 기억한 후 다양한 곳에 많이 활용할 수 있도록 기록해보는 오늘의 포스팅,,,끝~🎅🏻