Búsqueda de sitios web

typescript - Extraer la función pasada a Promise.catch genera un error de tipo


Soy nuevo en Typescript y estoy intentando entender un error de tipo. En el código de abajo, que he simplificado, la función ok se compila bien, pero cuando extraigo la función handleError, ya no pasa la verificación de tipos. Hasta donde puedo ver, el código es idéntico ya que todo lo que hice fue extraer una función, pero obviamente hay algo aquí que no entiendo. ¿Puedes ayudarme a entender por qué está sucediendo esto y si hay alguna manera de solucionarlo?

Aquí está el código que compila bien

  const ok = <T>(): Promise<AxiosResponse<T>> =>
    axios.post<T>('http://example.com', {}, {}).catch(
      (params: AxiosError<T>): Promise<AxiosResponse<T>> => {
        return Promise.reject<AxiosResponse<T>>(params)
      }
    )

Y aquí está el código que no lo hace.

  const handleError = <T>(params: AxiosError<T>): Promise<AxiosResponse<T>> => {
    return Promise.reject<AxiosResponse<T>>(params)
  }

  const notOk = <T>(): Promise<AxiosResponse<T>> =>
    axios.post<T>('http://example.com', {}, {}).catch(handleError)

El error que recibo es

Type 'Promise<AxiosResponse<T> | AxiosResponse<{}>>' is not assignable to type 'Promise<AxiosResponse<T>>'.
  Type 'AxiosResponse<T> | AxiosResponse<{}>' is not assignable to type 'AxiosResponse<T>'.
    Type 'AxiosResponse<{}>' is not assignable to type 'AxiosResponse<T>'.
      Type '{}' is not assignable to type 'T'.  TS2322

    46 | const notOk = <T>(): Promise<AxiosResponse<T>> =>
    47 |   axios.post<T>('http://example.com', {}, {}).catch(handleError)
  > 48 |
       | ^

Mi suposición es que se pierde algún tipo de información y que handleError necesita que se le diga qué es T, pero no estoy seguro de cómo hacer eso.

Aquí hay un codesandbox en caso de que ayude a inspeccionar.

Respuesta #1

El error ocurre porque el bloque catch no sustituye el genérico en tu función handleError. Para resolver este problema debes hacerlo manualmente (ejemplo)

export const notOk = <T>(): Promise<AxiosResponse<T>> =>
  axios.post<T>("http://example.com", {}, {}).catch(error => handleError<T>(error));

Otra solución es crear un tipo genérico predeterminado para handle error (por ejemplo)

const handleError = <T = any>(
  params: AxiosError<T>
): Promise<AxiosResponse<T>> => {
  return Promise.reject<AxiosResponse<T>>(params);
};