如何使用 ...rest ...spread 正确键入函数包装器以获取重载?

How to correctly type a function wrapper using ...rest ...spread to pick up overloads?

我正在尝试从 Axios npm package.

axios 函数制作一个包装器

函数可以这样调用

axios(config: AxiosRequestConfig) 
// When URL is contained inside config

axios(
   url: string,
   config: AxiosRequestConfig, 
)
// when it's not

我的简单包装看起来像这样:

import axios from 'axios'

type AxiosArguments = Parameters<typeof axios>
const axiosWrapper = async (...args: AxiosArguments) => await axios(...args)

export default axiosWrapper

但是这种方式 TypeScript 不会接受重载 - 当我尝试时

export const fetchSomething = () => wrappedAxios({
    url: '/url/to/something/',
    method: 'get',
})

我收到一个错误:

Error:(5, 60) TS2345: Argument of type '{ url: string; }' is not assignable to parameter of type 'string'.

如何让它发挥作用?我更愿意学习一般性的做法,而不是仅仅从 Axios 导入正确的类型。

我可能会使用 function overload:

async function axiosWrapper(config: AxiosRequestConfig): Promise<AxiosReturnValue>;
async function axiosWrapper(url: string, config: AxiosRequestConfig): Promise<AxiosReturnValue>;
async function axiosWrapper(urlOrConfig: string|AxiosRequestConfig, config?: AxiosRequestConfig): Promise<AxiosReturnValue> {
    if (typeof urlOrConfig === "string") {
        // The version with a URL
        return /*...*/;
    }
    // The version without
    return /*...*/;
}

AxiosReturnValue是上面的占位符。您希望它是您从包装器中 return 得到的任何东西。如果您正在 returning 什么 axios 是 returning,请使用相同的 return 类型。 (如果那是 Promise 类型,直接使用它,而不是在 Promise 内。因此,例如,如果 axios 的 return 类型是 Promise<Something>,请使用 Promise<Something>,而不是 Promise<Promise<Something>>。)

looks like axios 使用通用 return 类型 AxiosResponse<T>。如果是这样,那么:

async function axiosWrapper<T>(config: AxiosRequestConfig): Promise<AxiosResponse<T>>;
async function axiosWrapper<T>(url: string, config: AxiosRequestConfig): Promise<AxiosResponse<T>>;
async function axiosWrapper<T>(urlOrConfig: string|AxiosRequestConfig, config?: AxiosRequestConfig): Promise<AxiosResponse<T>> {
    if (typeof urlOrConfig === "string") {
        // The version with a URL
        return /*...*/;
    }
    // The version without
    return /*...*/;
}