typescript - ¿Cómo tipar correctamente un envoltorio de función usando ...rest ...spread para captar sobrecargas?
Estoy intentando hacer un envoltorio para la función axios del paquete npm Axios.
La función se puede llamar de cualquiera de las dos maneras
axios(config: AxiosRequestConfig)
// When URL is contained inside config
o
axios(
url: string,
config: AxiosRequestConfig,
)
// when it's not
mi envoltorio sencillo se ve así:
import axios from 'axios'
type AxiosArguments = Parameters<typeof axios>
const axiosWrapper = async (...args: AxiosArguments) => await axios(...args)
export default axiosWrapper
sin embargo, de esta manera TypeScript no detecta la sobrecarga - cuando trato
export const fetchSomething = () => wrappedAxios({
url: '/url/to/something/',
method: 'get',
})
Recibo un error:
Error:(5, 60) TS2345: El argumento de tipo '{ url: string; }' no es asignable al parámetro de tipo 'string'.
¿Cómo hago que funcione? Preferiría aprender a hacer esto en general en lugar de simplemente importar el tipo correcto de Axios.
Respuesta #1
Probablemente usaría una sobrecarga de función:
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 es un marcador de posición en lo anterior. Querrías que sea lo que sea que estés retornando desde tu envoltorio. Si estás retornando lo que axios está retornando, usa el mismo tipo de retorno que usa. (Si eso es un tipo Promise, úsalo directamente, no dentro de Promise. Por ejemplo, si el tipo de retorno de axios es Promise<Something>, usa Promise<Something>, no Promise<Promise<Something>>.)
Parece que axios utiliza un tipo de retorno genérico, AxiosResponse<T>. Si es así, entonces:
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 /*...*/;
}
