타입스크립트가 자체적으로 제공하는 특수한 타입들을 말한다.
export interface IProfile {
name: string
age: number
school: string
hobby?: string
}
// 1.patial 타입(전부 다 ? 달아줌)
type aaa = Partial<IProfile>
// 2.Required(전부 필수)
type bbb = Required<IProfile>
// 3.Pick 타입(일부만 가져오기)
type ccc = Pick<IProfile, "name"|"age">
// 4. Omit 타입(일부 제거)
type ddd = Omit<IProfile, "school">
// 5. Record 타입
type eee = "철수" | "영희" | "훈이" // Union 타입
let child:eee = "철수" //철수,영희,훈이 중에서만 선택 가능
let child2:string = "사과" //모든 문자열 가능
type fff = Record<eee, IProfile> //eee는 Key로, IProfile은 value로 바뀜.
// 6. 객체의 key들로 union타입 만들기
type ggg = keyof IProfile //"name" | "age" | "school" | "hobby"
let myprofile:ggg = "hobby"
// 7. type vs interface 차이 => 선언 병합
export interface IProfile {
candy:number //선언 병합으로 추가 됨.
}
// 8. 응용
let profile:Partial<IProfile> = {
candy: 10,
}
위 예시 코드 이외에도 다양한 utility type이 존재한다
(참고: 공식 문서 바로가기)
Partial
객체의 모든 프로퍼티에 ?(optional chaining)을 부여한다.
즉 선택적으로 만든다.
Required
객체의 모든 프로퍼티를 필수적으로 만든다.(optional chaining 제거)
Pick
Pick<T, K>는 T 타입의 프로퍼티 중 K로 지정한 프로퍼티만을 포함한 새로운 타입을 만든다.
Omit
Omit<T, K>는 T 타입의 프로퍼티 중 K로 지정한 프로퍼티를 제외한 새로운 타입을 만든다.
Record
Record<K, V> 유틸리티 타입은 K로 지정한 프로퍼티 키들이 V로 지정한 값을 가지는 객체 타입을 만든다.
그리고, 이때 V를 Union타입이라고 말한다.
Typescript를 공부하면서 비록 타입을 매번 지정해줘야 하는 것은 번거로운 과정일 수도 있다는 생각이 들지만, 그만큼 장점이 뚜렷하기에 포기할 수 없는 것 같다.
restAPI나 graphql에서 API 응답 데이터를 받아올 때 조차도 타입스크립트에서는 받아오는 데이터들의 타입을 요구한다. 그런데, 이것은 쉽지 않은 일이다.
rest-api는 타입스크립트를 적용하게 되면 어느정도 일일히 손으로 만들어야 하는 부분이 많다.
하지만 graphql 같은 경우는 graphql-codegen을 이용해 명령어 하나로 만들어준다.
따라서 굉장히 간편하게 만들 수 있다.
graphql-code-generator 홈페이지 접속(https://www.graphql-code-generator.com/) 또는 구글에서 graphql-codegen을 검색
Try It Now 를 클릭
좌측 메뉴의 Installation을 클릭
각자의 패키지 매니저에 맞는 명령어를 복사후 작업 할 폴더의 위치에서 붙여넣어 준다.
npm : npm install -D @graphql-codegen/cli
yarn : yarn add -D @graphql-codegen/cli
그러나, 지금은 이것을 바탕으로 타입스크립트를만들어 낼 것이기 때문에 뒤에 cli를 지운 후 tyscript를 입력해준다.
npm : npm install -D @graphql-codegen/typescript
yarn : yarn add -D @graphql-codegen/typescript
package.json은 {}가 중요한 파일 이었지만, yaml파일은 아래와 같이 {}가 없기때문에 들여쓰기가 중요한 파일이다.
이때! Tab 들여쓰기와 Space bar 들여쓰기를 구분하니, 반드시 Space bar를 사용해준다.
//codegen.yaml 파일 (yml, yaml 둘 다 상관 없습니다.)
schema: "API 호출 할 백엔드 주소"
generates:
./src/commons/types/generated/types.ts:
plugins:
- typescript
config:
typesPrefix: I
schema에는 graphql url 주소(백엔드 주소)를 넣어준다.(app.js의 uri 주소와 동일하게)
이후에 명령어로 codegen을 실행시키시면 스키마의 주소로 들어가 api들의 타입을 쭉 다운받아오는데, 다운받은 타입을 generates의 type.ts로 들어가게 된다. (미리 생성)
type.ts의 파일위치는 임의로 바꾸어도 무방하다.
plugin 에는 typescript만 남기고 지워준다.
typesPrefix:I 부분은 받아올 type이름 앞에 I를 붙여서 받아오도록 하는 것이다.
BoardProject를 진행하면서 처음에 variables로 무엇을 보내줄지, 응답으로 무엇을 받아올 지 잘 몰랐다.
그래서 지금까지는 data를 받아올 때 타입에 any를 적어줬었다.
하지만, 이제 codegen을 사용하면서 graphql의 타입을 모두 다운 받아 왔다. 따라서 다운 받아온 타입중에 맞는것을 뽑아 적어주면 된다..
// 응답 타입과 variables타입은 타입파일에 다운로드 되어있기 때문에 맞는걸로 import해서 데리고 오시면 됩니다.
const [qqq] = useMutation<응답 타입,variables 타입>()
/* 실제 코드에 적용해보기 */
// 다운로드된 타입들 중 맞는 타입을 데리고 올때는 Pick을 이용하며 해당 타입을 import해와야 합니다.
//강의에서는 타입파일에서 Mutation과 MutationCreateBoardArgs를 import해왔습니다.
// 우리는 Mutation 중에서 createBoard를 픽해올 것 입니다.
const [qqq] = useMutation<Pick<Mutation,"createBoard">,MutationCreateBoardArgs>(CREATE_BOARD)
const zzz = async () => {
const result = await qqq(CREARTE_BOARD)
console.log(result.data?.createBoard?.message)
}
useState와 useMutation같은 부분들은 위와 같이 소괄호가 시작하기 전 꺽쇠<>를 이용해서 타입을 지정해준다.
query에서도 마찬가지이다.
// 응답타입과 variables 타입은 타입파일에 다운로드 되어있기 때문에 맞는걸로 import해서 데리고 오시면 됩니다.
const { data } = useQuery<Pick<Query,"fetchBoard">,QueryFetchBoardArgs>(FETCH_BOARD,{
variables: {number:Number(router.query.mynumber)}
})