- 타입스크립트에서
keyof
연산자는 객체 타입을 받아 해당 객체의 키값을 string
또는 number
의 리터럴 유니온 타입을 반환한다.
| interface ColorType { |
| red: string; |
| green: string; |
| blue: string; |
| } |
| |
| type ColorKeyType = keyof ColorType; // 'red' | 'green' | 'blue' |
- 타입스크립트에서
typeof
연산자는 변수 혹은 속성의 타입을 추론하는 역할을 한다.
| const colors = { |
| red: '#F45452', |
| green: '#0C952A', |
| blue: '#1A7CFF', |
| }; |
| |
| type ColorsType = typeof colors; |
| /** |
| type ColorsType = { |
| red: string; |
| green: string; |
| blue: string; |
| } |
| */ |
as const
키워드로 객체를 불변 객체로 선언하고, keyof
연산자를 사용하여 함수 인자로 존재하는 속성만 받도록 설정할 수 있다.
- 객체 타입을 구체적으로 설정하면 타입에 맞지 않는 값을 전달하는 경우를 방지할 수 있고 자동 완성 기능을 통해 객체에 어떤 값이 있는지 쉽게 파악할 수 있다.
| type Key = keyof typeof colors; |
| |
| const colors = { |
| red: '#F45452', |
| green: '#0C952A', |
| blue: '#1A7CFF', |
| } as const; |
| |
| export const getColorHex = (key: Key) => colors[key]; |
Atom 컴포넌트에 활용하기
- Atom 단위의 작은 컴포넌트(Button, Header, Input 등)는 폰트 크기, 폰트 색상, 배경 색상 등 다양한 환경에서 유연하게 사용할 수 있도록 구현되어야 하는데 이러한 설정값은 props로 넘겨주도록 설계한다.
- 대부분의 프로젝트에서는 해당 프로젝트의 스타일 값을 관리해주는 theme 객체를 두고 관리한다.
keyof
, typeof
연산자를 사용하면 theme 객체 타입을 구체화할 수 있다.
| const colors = { |
| black: '#000000', |
| gray: '#222222', |
| white: '#FFFFFF', |
| red: '#F45452', |
| green: '#0C952A', |
| blue: '#1A7CFF', |
| mint: '#2AC1BC', |
| } as const; |
| |
| export const theme = { |
| color: { |
| default: colors.gray, |
| ...colors, |
| }, |
| bgColor: { |
| default: colors.white, |
| gray: colors.gray, |
| mint: colors.mint, |
| black: colors.black, |
| }, |
| fontSize: { |
| default: '16px', |
| small: '14px', |
| large: '18px', |
| }, |
| }; |
| |
| export const getColorHex = (key: Key) => colors[key]; |
| |
| type Key = Exclude<ColorType, 'default'>; |
| export type ColorType = keyof typeof theme.color; |
| export type BackgroundColorType = keyof typeof theme.bgColor; |
| export type FontSizeType = keyof typeof theme.fontSize; |
- 구체화된 theme 객체 타입을 사용하면 컴포넌트 props의 타입을 구체화하여 실수를 방지할 수 있고 자동 완성 기능을 제공받을 수 있다.
- 여러 상숫값을 인자나 props로 받은 다음에 객체의 키값을 추출한 타입을 활용하면 객체에 접근할 때 타입스크립트의 도움을 받아 실수를 방지할 수 있다.
| import { FC } from 'react'; |
| import styled from 'styled-components'; |
| import { |
| BackgroundColorType, |
| ColorType, |
| FontSizeType, |
| theme, |
| } from '../../styles/theme'; |
| |
| interface Props { |
| color?: ColorType; |
| backgroundColor?: BackgroundColorType; |
| fontSize?: FontSizeType; |
| children: React.ReactElement; |
| onClick?: ( |
| event: React.MouseEvent<HTMLButtonElement> |
| ) => void | Promise<void>; |
| } |
| |
| const Button: FC<Props> = ({ |
| fontSize, |
| backgroundColor, |
| color, |
| children, |
| onClick, |
| }) => { |
| return ( |
| <ButtonWrap |
| fontSize={fontSize} |
| backgroundColor={backgroundColor} |
| color={color} |
| onClick={onClick} |
| > |
| {children} |
| </ButtonWrap> |
| ); |
| }; |
| |
| export default Button; |
| |
| const ButtonWrap = styled.button<Omit<Props, 'onClick'>>` |
| color: ${({ color }) => theme.color[color ?? 'default']}; |
| background-color: ${({ backgroundColor }) => |
| theme.bgColor[backgroundColor ?? 'default']}; |
| font-size: ${({ fontSize }) => theme.fontSize[fontSize ?? 'default']}; |
| `; |