@graphiql-codegen/typescript-resolvers에서 상호 의존적인 속성의 유형 정의를 제시합니다

개시하다


GraphiQL API 모드가 알려진 경우 graphql-codegen에서 TypeScript 유형 정의를 생성할 수 있습니다.
@graphql-codegen/typescript-resolvers를 사용한 후 Resolver의 유형 정의를 출력하고 모델링 정의를 받은 상태에서 Apollo Server를 제작합니다."이런 스타일의 실사는 이상하지 않나요?"하는 상태[1]를 방지할 수 있습니다. 여기까지 써주시니 다행입니다..

난처하다


예를 들어 다음의GraphiQL 모델을 고려해 봅시다.Post.createdByUser.posts의 유형은 서로 의존합니다.
./schema.graphql
type Post {
  id: ID!
  title: String!
  createdBy: User!
}

type User {
  id: ID!
  name: String!
  posts: [Post!]!
}

type Query {
  post(id: ID!): Post!
}
이 모드에서는 다음 질의를 사용할 수 있습니다.
GetPosts.graphql
query GetPosts {
  post(id: "hoge") {
    id
    createdBy {
      id
      name
      posts {
        id
	title
      }
    }
  }
}
Apollo ServerResolver Chain를 고려하면 이런 Resolver를 쓰면 움직일 것 같다[2]
server.ts
type Post = {id: string; title: string; createdBy: {id: string};}
type User = {id: string; name: string; posts: {id: string}[];}

type getPost = (postId: string) => Post
type getPosts = (postIds: {id: string}[]) => Post[]
type getUser = (userId: string) => User

const resolver = {
  Query: {
    post(parent, args: {id: string}) {
      return getPost(id)
    }
  },
  Post: {
    createdBy(parent: Post) {
      return getUser(id)
    }
  },
  User: {
    posts(parent: User) {
      return getPosts(parent.posts) // この辺りとかそんな雑な実装無いだろとは思いますが まあとりあえず
    }
  }
}
그 전에 코드젠은 등장하지 않고 자신의 힘으로 주는 형. 여기resolver형은 코드젠으로 만들고 싶은 욕구가 생겼다.
./codegen.yml
schema: ./schema.graphql

generates:
  ./codegen/resolvers.ts:
    plugins:
      - typescript
      - typescript-resolvers
    config:
      useIndexSignature: true
그런데...

문제가 생기다


여기 나오는 것만 간단히 사용하면codegen/resolvers.ts 문제가 생길 수 있어요.
자동으로 생성되는 유형 정의가 "카페"로 쓰이면 복잡하고 길기 때문에 역할을 하지만 쉽게 말하면 이런 상태입니다.
./codegen/resolvers.ts
type Post = {
  id: string;
  title: string;
  createdBy: User;
};

type User = {
  id: string;
  name: string;
  posts: Post[];
};

type Resolver = {
  Query: {
    post(parent: {}, args: {id: string}): Post;
  };
  Post: {
    createdBy(parent: Post): User;
  };
  User: {
    posts(parent: User): Post[];
  };
};
PostUser 상호 순환
이 유형의 정의에 따라 실시한다면 예를 들면 필요Query.post.createdBy.posts[0].createdBy.posts[0]...와 당당한 실시가 필요하다. 물론 그렇게 말해도 곤란하지만 어떻게 하면 좋을까?

솔루션


문서에 기록된 https://www.graphql-code-generator.com/docs/plugins/typescript-resolvers#use-your-model-types-mappers을 설정합니다. mapper.
codegen.yml
schema: ./schema.graphql

generates:
  ./codegen/resolvers.ts:
    plugins:
      - typescript
      - typescript-resolvers
    config:
      useIndexSignature: true
      mappers:
        Post: ./types#PostModel
        User: ./types#UserModel
이 설정은 ./codegen/resolvers.ts에서 목표 디렉터리 생성./types.ts, 즉 ./codegen/types.ts 참조 exportPostModel의 정보를 전달합니다.
그럼 codegen.yml 이런 느낌으로 서로 의지하지 않는 형식을 정의해보자. Apollo의 Resolver Chain을 더하면 충분해.
./codegen/types.ts
export type PostModel = {
  id: string;
  title: string;
  createdBy: {id: string};
};

export type UserModel = {
  id: string;
  name: string;
  posts: {id: string}[];
};
설정을 변경한 후 생성된 Resolver의 유형 정의./codegen/types.ts에서 출력된 유형이 이용되는 느낌
./codegen/resolvers.ts
import {PostModel, UserModel} from "./types"

type Resolver = {
  Query: {
    post(parent: {}, args: {id: string}): PostModel;
  };
  Post: {
    createdBy(parent: Post): UserModel;
  };
  User: {
    posts(parent: User): PostModel[];
  };
};
이렇게 하면 ./types 적당히 잘릴 수 있어 다행이야
다음은 서버 설치에서 이걸로 쓰는 절차입니다.

끝말


기타 "Context 타입 and 어떡해"등의 문제도 해결할 수 있습니다.
이 기사에 쓰인 코드와 기타 각양각색의 내용은 대충 옳다고 믿지만, 공문서이기 때문에 완전히 틀렸을 수도 있습니다. 요점은 설정Query.post.createdBy하면 됩니다.
이 기사는 제작 중이것 때 직면한 문제에 관한 기사입니다. 가능하면 한번 보세요.
끝맺다
각주
그리고 단순한 코드 보완이 효과가 있어 기분 좋게 코드를 쓸 수 있다↩︎
이번에 데이터를 얻은 부분은 무엇이든지 가능하기 때문에 실제 포장을 쓰지 않고 형식만 표시↩︎

좋은 웹페이지 즐겨찾기