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

自定义SWR Hook返回类型与预期类型不匹配问题排查

解决SWR泛型Hook生成器的类型推断问题

我在使用SWR库开发一个基于泛型的Block Hook生成器,输入mapParamsToKey和request方法来生成对应的SWR Hook,但生成的Hook返回的SWRResponse类型不符合预期——data的类型被推断为any,而不是request方法返回的Promise泛型类型。

问题代码示例

import useSWR from 'swr';

type Params = {
  id: number;
};
type BlogPost = {
  id: number;
  title: string;
};

const mapParamsToKey = (params: Params) => ['blog-post', params.id];
const request = (params: Params): Promise<BlogPost> => {
  const data = { id: params.id, title: `Blog Post ${params.id}` };
  return Promise.resolve(data);
};

// 手动编写的Hook能正确推断出SWRResponse<BlogPost, any, any>
const useBlogPost = (params: Params) =>
  useSWR(mapParamsToKey(params), () => request(params)); 

// 泛型Hook生成器
function createBlockHook<P, T = any>(config: {
  mapParamsToKey: (params: P) => Array<string | number>;
  request: (params: P) => Promise<T>;
}) {
  return (params: P) =>
    useSWR(config.mapParamsToKey(params), () => config.request(params));
}

// 生成的Hook返回SWRResponse<any, any, any>,不符合预期
const useBlogPost2 = createBlockHook<Params>({
  mapParamsToKey,
  request,
}); 

解决方案

问题根源在于泛型参数T的默认值设置:当你只显式指定<Params>时,T会使用默认值any,而不会自动从request方法的返回值中推断类型。可以通过两种方式修复:

方式1:移除T的默认值,让TypeScript自动推断所有泛型参数

修改createBlockHook的泛型定义,去掉T的默认值any,调用时无需手动指定泛型参数,TypeScript会自动从传入的config中推断P和T:

function createBlockHook<P, T>(config: {
  mapParamsToKey: (params: P) => Array<string | number>;
  request: (params: P) => Promise<T>;
}) {
  return (params: P) =>
    useSWR(config.mapParamsToKey(params), () => config.request(params));
}

// 自动推断P=Params,T=BlogPost,返回SWRResponse<BlogPost, any, any>
const useBlogPost2 = createBlockHook({
  mapParamsToKey,
  request,
}); 

方式2:显式指定所有泛型参数

如果需要手动指定P的类型,同时也要显式指定T的类型,确保类型匹配:

const useBlogPost2 = createBlockHook<Params, BlogPost>({
  mapParamsToKey,
  request,
}); 

修正后的预期使用场景

import client from './my-api-client';
type CommentParams = { id: number; } 
const useComment = createBlockHook({
  mapParamsToKey: (params) => ['comment', params.id], 
  request: client.getComment, // (params: CommentParams) => Promise<Comment>
}); 

function Comment(props: { id: number }) {
  const swr = useComment(props); 
  if (swr.data) {
    // swr.data现在会正确提示Comment类型
    return (
      <div>{swr.data.content}</div>
    )
  }
  return <div>...</div>;
}

内容的提问来源于stack exchange,提问作者feat.com

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.13 06:35:17