[스터디] 우테코 프로젝트의 type코드를 열어보자!

정(JJeong)·2023년 4월 18일
1

스터디 기록

목록 보기
2/5
post-thumbnail

이전엔 궁금한 cofig파일을 먼저 열어보았고, 이번엔 이번 스터디의 가장 핵심인 types들을 열어보았다.

⭐스터디에 참고하는 프로젝트는 🐰달롱의 레포를 사용합니다.⭐


interface를 타입으로

일단 기능 중에 달롱 프로젝트의 일정관리 기능에서 (개인적으로) 중요해 보이는 카테고리와 관련된 ts파일을 열어보았는데 가장 먼저 살펴볼만한 건 만들어둔 interface를 타입으로 설정하는 것이었다.

처음 타입스크립트를 시작하고 가장 쉽게 시도해볼 수 있는 방식.

category.ts

import { ProfileType } from '@/@types/profile';
import { ValueOf } from '@/@types/util';

import { CATEGORY_TYPE, ROLE } from '@/constants/category';

type CategoryRoleType = ValueOf<typeof ROLE>;

interface CategoryType {
  id: number;
  name: string;
  creator: ProfileType;
  createdAt: string;
  categoryType: ValueOf<typeof CATEGORY_TYPE>;
};

interface CategorySubscriberType {
  member: ProfileType;
  categoryRoleType: CategoryRoleType;
};

interface SingleCategoryType extends CategoryType {
  subscriberCount: number;
};

주목해야하는 것은 ProfileTypeValueOf<typeof CATEGORY_TYPE> 그리고 CategoryRoleType인 것 같다.
따라가보자.

SingleCategoryType는 CategoryType을 확장하여 사용하고 있다.


profile.ts

interface ProfileType {
  id: number;
  email: string;
  displayName: string;
  profileImageUrl: string;
  socialType: string;
};

// ...

profile.ts에서 선어되어 있는 interfacte에 따라서 카테고리 타입 정보에 들어갈 creater, 즉 작성자에 대한 info를 가져오는 것을 볼 수 있을 것 같다.


keyof연산자 활용하기

다음으로 ValueOf<typeof CATEGORY_TYPE>CategoryRoleType를 살펴보면 되는데,,,

일단 먼저 이해해야 할 것이 있다. 둘다 ValueOf<T>의 형태를 띄고 있다. 그래서 이걸 먼저 알기 위해 util.ts를 열어보았다.

👀짚고가기: CategoryRoleType = ValueOf<typeof ROLE>;


util.ts

type ValueOf<T> = T[keyof T];

util.ts를 열어보면 위 같은 구조를 띄고 있다. 여기서 keyof연산자를 사용하여 T라는 객체로 들어오게될 제네릭의 value값을 읽어낸다고 이해할 수 있을 것이다.

이제 ValueOf<T>에 대해 이해했으니 다시 ValueOf<typeof CATEGORY_TYPE>CategoryRoleType를 보러가자.

이는 import된 경로를 보면 constants폴더 쪽에 위치해 있다.


constants > category.ts

const CATEGORY_TYPE = {
  GOOGLE: 'GOOGLE',
  NORMAL: 'NORMAL',
  PERSONAL: 'PERSONAL',
};

const ROLE = {
  ADMIN: 'ADMIN',
  NONE: 'NONE',
};

카테고리가 어떤 타입인지에 대해 리터럴 타입으로 상수화하여 만들어 놓고 불러와 사용하는 것을 볼 수 있다.

이 부분은 차후에 변화가 있을 부분이 아니다보니 리터럴 타입으로 목록을 만들어 놓고 ValueOf<typeof CATEGORY_TYPE>로 불러와서 categoryType에 CATEGORY_TYPE의 value값만 사용 가능하도록 한 것으로 보인다.

마찬가지로 categoryRoleTypeValueOf<typeof ROLE>을 통해 ROLE에서의 value값만 사용되도록 한 것이라 이해할 수 있을 것이다.



좀더 살펴보기

category와 관련된 type을 따라가며 몇가지 파일을 열어봤는데 보는 김에 다른 파일도 열어보며 내가 공부했던 것들이 사용되는 부분들을 살펴보았다.

emotion.d.ts

interface ColorsType {
  [key: string]: string;
}

type FlexType = Record<'row' | 'column', SerializedStyles>;

// ...

먼저 [key: string]라고 인덱스 시그니쳐를 사용해서 key값이 string만 되도록 한 것을 볼 수 있다.

그리고 아래에선 제네릭에 들어갈 수 있는 값을 유니온 타입으로 선언한 것으로 보이는데 Record가 어디서 온건지 모르겠다.. 얘는 다시 찾아보는 걸로.


index.ts

import { SerializedStyles } from '@emotion/react';

interface FieldsetCssPropType {
  div?: SerializedStyles;
  input?: SerializedStyles;
  label?: SerializedStyles;
}

interface SelectCssPropType {
  select?: SerializedStyles;
  optionBox?: SerializedStyles;
  option?: SerializedStyles;
}

interface InputRefType {
  [index: string]: React.RefObject<HTMLInputElement>;
}

// ...

일단 emotion라이브러리에서 불러와 SerializedStyles라는 것을 타입으로 지정해주는 것으로 보인다.

그리고 InputRefType에서는 emotion.d.ts에서 봤던 것처럼 인덱스 시그니쳐을 이용했다.


schedule.ts

import { ValueOf } from '@/@types/util';

import { CATEGORY_TYPE } from '@/constants/category';
import { SCHEDULE } from '@/constants/schedule';

type ScheduleResponseKeyType = ValueOf<typeof SCHEDULE.RESPONSE_TYPE>;

type ScheduleResponseType = Record<ScheduleResponseKeyType, Array<ScheduleType>>;

// ...

여기서도 일단은 ValueOf<T>가 쓰인 것을 볼 수 있다. 그리고 Record도 다시 쓰였는데..

이제 이쯤에서 Record를 찾아보자.


Record<T>

lib.es5.d.ts

/**
 * Construct a type with a set of properties K of type T
 */
type Record<K extends keyof any, T> = {
    [P in K]: T;
};

찾아보니 Record<K, T>는 유틸리티 타입으로써 key값과 value값을 제네릭으로 받아 새로운 {key: value}형식의 타입을 반환해준다.

👀 신기하다 신기해.

이 외에도 다른 유틸리티 타입이 더 있으니 좀더 알아봐야겠다.



첫 오픈소스 열어보기는 여기서 마무리.

profile
2년차 응애 FE 개발자입니다👶

2개의 댓글

comment-user-thumbnail
2023년 4월 18일

잘 정리해주셔서 감사합니다!!

1개의 답글