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

基于函数参数为Axios返回值定义条件类型的TypeScript问题

基于函数参数为Axios返回值定义条件类型的TypeScript问题

嘿,我看你在写axiosGet工具函数的时候遇到了TypeScript类型推断的问题——当params里没有paginate时,取r.data.data会报错对吧?这是因为你还没把paginate的存在与否和Axios返回值的类型结构关联起来,咱们一步步来解决它。

先把你提供的代码片段放出来方便参考:

export const axiosGet = async <TData>({
    url,
    params = {},
    onDone,
    onError
}: TypeAxiosArgs<TData>) => {
        
    try {
        const r = await axios.get<TypeAxiosData<TData, typeof params.paginate>>(url, { params })
        let ret
        if (params?.paginate) {
            ret = r.data
        } else {
            ret = r.data.data // <--- causing typescript to scream, check below
        }
        // 省略后续逻辑...
    } catch (err) {
        // 错误处理...
    }
}

问题根源

当前的TypeAxiosData类型没有根据paginate的取值做条件分支,TypeScript没办法确定r.data到底是直接的TData,还是包含data属性的对象,所以会在r.data.data这里抛出类型错误。

解决方案:用条件类型关联参数与返回值结构

我们需要修改类型定义,让TypeScript能根据params.paginate的取值,自动推断Axios返回值的结构。

第一步:完善参数与返回值的类型定义

// 定义参数类型,明确paginate是可选布尔值,同时保留其他自定义参数
type TypeAxiosArgs<TData, TPaginate extends boolean = false> = {
  url: string;
  params?: { paginate?: TPaginate } & Record<string, unknown>;
  onDone?: (data: TData) => void;
  onError?: (error: unknown) => void;
};

// 根据paginate的取值,定义Axios返回的data结构
type TypeAxiosData<TData, TPaginate> = TPaginate extends true
  ? TData // 当paginate为true时,返回值data直接是TData类型
  : { data: TData }; // 当paginate不存在或为false时,返回值data是包含data属性的对象

第二步:修改函数逻辑,让类型推断生效

import axios from 'axios';

export const axiosGet = async <TData, TPaginate extends boolean = false>({
  url,
  params = {},
  onDone,
  onError
}: TypeAxiosArgs<TData, TPaginate>) => {
  try {
    // 这里TypeScript会根据TPaginate的取值,自动匹配TypeAxiosData的结构
    const r = await axios.get<TypeAxiosData<TData, TPaginate>>(url, { params });
    let ret: TData;

    if (params.paginate) {
      ret = r.data; // 此时r.data的类型是TData,完全匹配
    } else {
      ret = r.data.data; // 此时r.data的类型是{ data: TData },取data属性不会报错
    }

    onDone?.(ret);
    return ret;
  } catch (error) {
    onError?.(error);
    throw error;
  }
};

为什么这样能解决问题?

我们把paginate的类型作为泛型参数TPaginate传入函数,TypeScript会在调用函数时自动捕获params.paginate的实际取值(true/false/undefined),然后通过TypeAxiosData的条件类型,精准推断出Axios返回值的结构,自然就不会在取值时抛出类型错误了。

比如当你这样调用函数时:

// TypeScript自动推断返回值是User[]类型
axiosGet<User[]>({ url: '/users', params: { paginate: true } });

// TypeScript自动推断返回值是User类型
axiosGet<User>({ url: '/users/1' });

备注:内容来源于stack exchange,提问作者K i

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.13 17:04:36