如何使用带有Typescript的泛型将中继(graphql)连接映射到边缘的节点

问题描述 投票:1回答:1

我最近一直在实验React,GraphQL,Apollo和Relay符合性查询。现在,我有一个GraphQL后端,该后端具有一个带有一些Connection查询的简单graphql模式用于返回可以使用中继服务器规范进行分页的实体列表。

在前端,我发现自己在做出上述查询后重复自己的代码通常如下所示:

type isDefined = <T>(value: T | null | undefined): value is T => value !== null && value !== undefined;

export const AppleListComponent: React.FC = () => {
  const { data } = useAppleQuery(); // FWIW, generating this with graphql-code-generator
  const apples = data && data.apples;
  const appleNodes = apples && apples.edges.map(apple => (
    apple ? apple.node : undefined
  )).filter(apple => isDefined(apple));

  return (
    <div>
      {appleNodes && appleNodes.map(apple => (
        <p key={apple.text}>{apple.text}</p>
      ))}
    </div>
  );
};

由于需要中继规范,所以必须检查存在的歌舞。边缘,并且节点可以为Nullable。我发现自己经常重复这种转变中继格式到简单的节点数组格式。我决定看看是否可以一个辅助函数,它需要符合连接接口的内容,并返回undefined或映射节点列表。该尝试看起来像这样:

type Maybe<T> = T | null;
type isDefined = <T>(value: T | null | undefined): value is T => value !== null && value !== undefined;

type Connection<T> = Maybe<{ edges: Array<Maybe<{ node: Maybe<T> }>>}>;

export const connectionToNodes = <T>(connection: Connection<T>): Maybe<T[]> => (
  connection && connection.edges.map(edge => (
    edge ? edge.node : undefined
  )).filter(isDefined)
);

哪个允许以前的组件成为

export const AppleListComponent: React.FC = () => {
  const { data } = useAppleQuery();
  const apples = data && data.apples;
  const appleNodes = connectionToNodes(apples);

  return (
    <div>
      {appleNodes && appleNodes.map(apple => (
        <p key={apple.text}>{apple.text}</p>
      ))}
    </div>
  );
};

我的问题是我的Connection类型当然不完全匹配根据我传递的类型,它具有更多类似于以下内容的属性:

Maybe<(
  { __typename?: 'AppleConnection' }
  & { edges: Array<Maybe<(
    { __typename?: 'AppleEdge' }
    & { node: Maybe<{ __typename?: 'AppleType' }
      & { __typename?: 'QuestionType' }
        & Pick<QuestionType, 'text'>
    > }
  )>> }
)>

因此,我最终收到有关任何类型问题的错误,以及我传递给connectionToNodes的内容与指定的类型不匹配。我的本能是我需要说我的类型T是其他某些事物的子类型-当然,出于应用目的,我不在乎它是Apple还是Pear连接/边缘/节点,但我希望最终可以推断出它-任何建议如何实现这一目标?

reactjs typescript graphql react-apollo relayjs
1个回答
0
投票

尝试使用此帮助程序从连接中提取节点

export type ExtractNode<T extends { edges: any }> = NonNullable<NonNullable<T['edges'][number]>['node']>;

用法

type Post = ExtractNode<FeedList_query['posts']>
© www.soinside.com 2019 - 2024. All rights reserved.