You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Apollo应用构建:TypeScript中GraphQL/Apollo类型问题求助

解决TypeScript下Apollo GraphQL多HOC组合的类型问题

嘿,我太懂你现在的困扰了——在TypeScript环境里用多个Apollo高阶组件(HOC)组合数据时,类型推断总是乱套,总怀疑是不是自己的实现思路出了问题对吧?其实这个问题挺常见的,核心在于Apollo的HOC在处理类型传递时,需要更明确的类型声明,不然TypeScript没法正确合并多个HOC注入的Props。

我给你几个针对性的解决方案,你可以一步步试:

  • 给每个HOC显式指定类型参数
    别依赖TypeScript的自动推断,给每个withQuery或withMutation明确声明数据结构和变量类型。比如:

    // 先定义查询返回的数据结构和变量类型
    interface ViewerData {
      viewer: { id: string; name: string };
    }
    interface ViewerVars { userId: string }
    
    const withViewer = withQuery<ViewerData, ViewerVars>(VIEWER_QUERY, {
      variables: { userId: "123" }
    });
    

    这样HOC注入的Props(比如data.viewer、data.loading)就会有精确的类型,不会和其他HOC的Props冲突。

  • 避免重复的Props键名
    多个HOC默认都会注入loading、error这类通用Props,直接合并肯定会有类型冲突。解决办法有两个:要么给查询结果加别名,要么在HOC里重命名注入的Props:

    // 方案1:给查询结果加别名
    const VIEWER_QUERY = gql`
      query ViewerQuery($userId: String!) {
        viewer: getUser(id: $userId) {
          id
          name
        }
      }
    `;
    
    // 方案2:在HOC的options里重命名Props
    const withViewer = withQuery(VIEWER_QUERY, {
      props: ({ data }) => ({
        viewer: data.viewer,
        viewerLoading: data.loading, // 把通用的loading重命名为viewerLoading
        viewerError: data.error
      })
    });
    

    这样每个HOC注入的Props都是唯一的,交叉类型合并时就不会有问题了。

  • 改用Hooks替代HOC(更推荐)
    现在Apollo官方更推荐用Hooks(useQuery、useMutation)来获取数据,TypeScript对Hooks的类型支持要比HOC好得多,而且不需要处理复杂的Props传递。比如把类组件改成函数组件:

    const Navigation: React.FC<Props> = ({ theme }) => {
      const { data: viewerData, loading: viewerLoading } = useQuery<ViewerData, ViewerVars>(VIEWER_QUERY, {
        variables: { userId: "123" }
      });
      const { data: pageData, loading: pageLoading } = useQuery<PageData, PageVars>(PAGE_QUERY);
    
      if (viewerLoading || pageLoading) return <Spinner />;
      if (!viewerData?.viewer || !pageData?.currentPage) return <NotFound />;
    
      return (
        <nav theme={theme}>
          {/* 直接用viewerData.viewer和pageData.currentPage渲染内容 */}
        </nav>
      );
    };
    

    这种方式完全不需要手动合并Props,类型推断直接生效,代码也更简洁直观。

  • 用compose时确保类型正确传递
    如果你坚持用HOC,一定要用Apollo提供的compose工具(或者react-compose),它会正确合并多个HOC的类型。比如:

    import { compose } from '@apollo/client';
    
    const NavigationContainer = compose(
      withViewer,
      withPage
    )(Navigation);
    

    这样TypeScript会自动把withViewer和withPage注入的Props合并到组件的Props类型里,你甚至不需要手动写Props & ViewerProps & PageProps(不过手动写也没问题,只要类型不冲突)。

最后再提醒一句:检查你的ViewerProps和PageProps是否和Props有重复的键,如果有,要么重命名,要么用Omit类型排除重复项(比如Omit<ViewerProps, 'theme'>)。

内容的提问来源于stack exchange,提问作者Innominate

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.22 08:18:08