如何在urql的createClient中异步设置fetchOptions?TypeScript报错解决
问题分析
你的代码报错核心原因是:createClient 的 fetchOptions 参数被类型定义为返回 RequestInit 的同步函数,但你传入了一个返回 Promise<RequestInit> 的异步函数,导致 TypeScript 类型不匹配。另外,authorization 字段传入空字符串也可能不符合 RequestInit.headers 的类型要求(通常该字段应为 string | undefined)。
解决方案
方案一:提前获取 Token 再初始化 Client
如果你的应用可以等待 Token 获取完成后再初始化 Client,这种方式最直接:
// 先声明 Client 变量 let apiClient: ReturnType<typeof createClient>; // 异步初始化 Client async function initializeClient() { const token = await retrieve(TOKEN_KEY); apiClient = createClient({ url, fetchOptions: () => ({ credentials: "include", headers: { // 空 Token 时直接传 undefined,符合类型要求 authorization: token ? `Bearer ${token}` : undefined }, }), }); } // 立即执行初始化 initializeClient(); // 导出确保 Client 已初始化的方法 export const getApiClient = () => { if (!apiClient) { throw new Error("API Client 尚未初始化,请等待初始化完成后再使用"); } return apiClient; };
如果需要在异步场景下使用,可将获取方法改为异步:
export async function getApiClient() { if (!apiClient) { await initializeClient(); } return apiClient; }
方案二:使用请求拦截器(推荐)
如果你的 API 客户端支持请求拦截器(多数现代客户端库都支持),可以在每次请求前动态获取 Token,无需提前初始化:
export const client = createClient({ url, fetchOptions: () => ({ credentials: "include", }), }); // 添加请求拦截器,每次请求前注入 Token client.use(async (request) => { const token = await retrieve(TOKEN_KEY); if (token) { request.headers.set("authorization", `Bearer ${token}`); } return request; });
方案三:类型断言(仅在确认类型安全时使用)
如果你确定客户端实际支持异步的 fetchOptions,只是类型定义未更新,可以用类型断言绕过检查:
export const client = createClient({ url, fetchOptions: (async () => { const token = await retrieve(TOKEN_KEY); return { credentials: "include", headers: { authorization: token ? `Bearer ${token}` : undefined }, }; }) as () => RequestInit, });
内容的提问来源于stack exchange,提问作者crispengari
相关产品推荐
相关产品推荐

