[TS] 불변 객체 타입

  • 타입스크립트에서 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']};
`;

'TypeScript' 카테고리의 다른 글

[TS] 런타임과 컴파일  (0) 2025.01.31
[TS] Record 원시 타입 키 개선  (1) 2025.01.30
[TS] NonNullable로 타입 가드  (0) 2025.01.28
[TS] 유틸리티 타입  (0) 2025.01.27
[TS] 조건부 타입  (0) 2025.01.26