TypeScript

emotion의 theme 타입 정의하기 (typeof 연산자)

presentKey 2024. 8. 20. 23:04
// theme.ts
export const theme = {
  colors: {
    blueGrey: colors.blueGrey,
    red: colors.red,
  },
};
// colors.ts
export const colors = {
  blueGrey: {
    50: '#F9FAFB',
    100: '#EBEEF2',
    200: '#CED5DF',
    300: '#B2BECC',
    400: '#95A7BA',
    500: '#788DA3',
    600: '#627384',
    700: '#53616F',
    800: '#434D58',
    900: '#323941',
  },
  red: {
    300: '#FFA59B',
    600: '#D62D36',
    700: '#B32A2E',
  },
};

프로젝트 내에 사용될 색상을 지정한 뒤 사용해보면 다음과 같은 type 오류가 발생한다. 

@emotion/react에 선언된 Theme 타입을 보면 빈 객체로 선언되있기 때문에 colors 속성 존재를 모르기 때문이다.

현재 프로젝트에 맞게 Theme 인터페이스를 확장할 필요가 있다.

 

🧷 typeof: https://www.typescriptlang.org/ko/docs/handbook/2/typeof-types.html

typeof 연산자를 통해 theme 객체의 타입(구조)를 그대로 가져와 ThemeType을 만들어준다.

 그 다음 emotion.d.ts 파일을 생성하여 Theme을 ThemeType으로 확장시키면 type오류가 사라진다.

// theme.ts
export const theme :Theme = {
  colors: {
    blueGrey: colors.blueGrey,
    red: colors.red,
  },
};

export type ThemeType = typeof theme;

 

// emotion.d.ts
import { ThemeType } from '@/styles/theme';
import '@emotion/react';

declare module '@emotion/react' {
  export interface Theme extends ThemeType {}
}

 

 

하지만 blueGrey 900이 string으로만 표시되기 때문에 정확히 어떤 값을 갖는지 알 수 없다. 

colors 객체에 as const 키워드를 붙여  객체의 각 요소를 리터럴 타입으로 유지할 수 있다.

리터럴 타입: 문자열이나 숫자에 정확한 값을 지정하는 것
// colors.ts
export const colors = {
  blueGrey: {
    50: '#F9FAFB',
    100: '#EBEEF2',
    200: '#CED5DF',
    300: '#B2BECC',
    400: '#95A7BA',
    500: '#788DA3',
    600: '#627384',
    700: '#53616F',
    800: '#434D58',
    900: '#323941',
  },
  red: {
    300: '#FFA59B',
    600: '#D62D36',
    700: '#B32A2E',
  },
} as const; // as const 키워드!

as const 전
as const 후