이전엔 궁금한 cofig파일을 먼저 열어보았고, 이번엔 이번 스터디의 가장 핵심인 types
들을 열어보았다.
⭐스터디에 참고하는 프로젝트는 🐰달롱의 레포를 사용합니다.⭐
일단 기능 중에 달롱 프로젝트의 일정관리 기능에서 (개인적으로) 중요해 보이는 카테고리와 관련된 ts파일을 열어보았는데 가장 먼저 살펴볼만한 건 만들어둔 interface
를 타입으로 설정하는 것이었다.
처음 타입스크립트를 시작하고 가장 쉽게 시도해볼 수 있는 방식.
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;
};
주목해야하는 것은 ProfileType
과 ValueOf<typeof CATEGORY_TYPE>
그리고 CategoryRoleType
인 것 같다.
따라가보자.
SingleCategoryType
는 CategoryType을 확장하여 사용하고 있다.
interface ProfileType {
id: number;
email: string;
displayName: string;
profileImageUrl: string;
socialType: string;
};
// ...
profile.ts에서 선어되어 있는 interfacte에 따라서 카테고리 타입 정보에 들어갈 creater, 즉 작성자에 대한 info를 가져오는 것을 볼 수 있을 것 같다.
다음으로 ValueOf<typeof CATEGORY_TYPE>
와 CategoryRoleType
를 살펴보면 되는데,,,
일단 먼저 이해해야 할 것이 있다. 둘다 ValueOf<T>
의 형태를 띄고 있다. 그래서 이걸 먼저 알기 위해 util.ts를 열어보았다.
👀짚고가기:
CategoryRoleType
=ValueOf<typeof ROLE>
;
type ValueOf<T> = T[keyof T];
util.ts를 열어보면 위 같은 구조를 띄고 있다. 여기서 keyof
연산자를 사용하여 T라는 객체로 들어오게될 제네릭의 value값을 읽어낸다고 이해할 수 있을 것이다.
이제 ValueOf<T>
에 대해 이해했으니 다시 ValueOf<typeof CATEGORY_TYPE>
와 CategoryRoleType
를 보러가자.
이는 import된 경로를 보면 constants폴더 쪽에 위치해 있다.
const CATEGORY_TYPE = {
GOOGLE: 'GOOGLE',
NORMAL: 'NORMAL',
PERSONAL: 'PERSONAL',
};
const ROLE = {
ADMIN: 'ADMIN',
NONE: 'NONE',
};
카테고리가 어떤 타입인지에 대해 리터럴 타입
으로 상수화하여 만들어 놓고 불러와 사용하는 것을 볼 수 있다.
이 부분은 차후에 변화가 있을 부분이 아니다보니 리터럴 타입으로 목록을 만들어 놓고 ValueOf<typeof CATEGORY_TYPE>
로 불러와서 categoryType에 CATEGORY_TYPE의 value값만 사용 가능하도록 한 것으로 보인다.
마찬가지로 categoryRoleType은 ValueOf<typeof ROLE>
을 통해 ROLE에서의 value값만 사용되도록 한 것이라 이해할 수 있을 것이다.
category와 관련된 type을 따라가며 몇가지 파일을 열어봤는데 보는 김에 다른 파일도 열어보며 내가 공부했던 것들이 사용되는 부분들을 살펴보았다.
interface ColorsType {
[key: string]: string;
}
type FlexType = Record<'row' | 'column', SerializedStyles>;
// ...
먼저 [key: string]
라고 인덱스 시그니쳐를 사용해서 key값이 string만 되도록 한 것을 볼 수 있다.
그리고 아래에선 제네릭에 들어갈 수 있는 값을 유니온 타입
으로 선언한 것으로 보이는데 Record가 어디서 온건지 모르겠다.. 얘는 다시 찾아보는 걸로.
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에서 봤던 것처럼 인덱스 시그니쳐을 이용했다.
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를 찾아보자.
/**
* 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}
형식의 타입을 반환해준다.
👀 신기하다 신기해.
이 외에도 다른 유틸리티 타입이 더 있으니 좀더 알아봐야겠다.
첫 오픈소스 열어보기는 여기서 마무리.
잘 정리해주셔서 감사합니다!!