Skip to content

TypeScript

INFO

La fuente original (en ingles) de este tutorial se encuentra aquí

¡Vue Query ahora está escrito en TypeScript para garantizar que la biblioteca y sus proyectos sean seguros para escribir!

Cosas a tener en cuenta:

  • Los tipos actualmente requieren el uso de TypeScript v4.7 o superior
  • Los cambios en los tipos en este repositorio se consideran no disruptivos y generalmente se publican como cambios de parches de versionado semántico (de lo contrario, cada mejora de tipos sería una versión principal).
  • Se recomienda encarecidamente que bloquee la versión de su paquete vue-query en una versión de parche específica y la actualice con la expectativa de que los tipos puedan corregirse o actualizarse entre cualquier versión.
  • La API pública no relacionada con el tipo de Vue Query todavía sigue versionado semántico muy estrictamente.

Inferencia de Tipos

Los tipos en Vue Query generalmente fluyen muy bien, por lo que no es necesario que usted mismo proporcione anotaciones de tipo.

ts
const { data } = useQuery({
  //    ^? const data: Ref<number> | Ref<undefined>
  queryKey: ['test'],
  queryFn: () => Promise.resolve(5),
})

typescript playground

ts
const { data } = useQuery({
  //      ^? const data: Ref<string> | Ref<undefined>
  queryKey: ['test'],
  queryFn: () => Promise.resolve(5),
  select: (data) => data.toString(),
})

typescript playground

Esto funciona mejor si su queryFn tiene un tipo devuelto bien definido. Tenga en cuenta que la mayoría de las bibliotecas de recuperación de datos devuelven any de forma predeterminada, así que asegúrese de extraerlo en una función escrita correctamente:

ts
const fetchGroups = (): Promise<Group[]> =>
  axios.get('/groups').then((response) => response.data)

const { data } = useQuery({ queryKey: ['groups'], queryFn: fetchGroups })
//      ^? const data: Ref<Group[]> | Ref<undefined>

typescript playground

Estrechamiento de Tipo

Vue Query utiliza un tipo de unión discriminada para el resultado de la consulta, discriminada por el campo status y los indicadores status de estado derivados. Esto le permitirá comprobar, por ejemplo status de success para definir data:

ts
const { data, isSuccess } = reactive(
  useQuery({
    queryKey: ['test'],
    queryFn: () => Promise.resolve(5),
  }),
)

if (isSuccess) {
  data
  // ^? const data: number
}

typescript playground

Tipar el Campo Error

El tipo de error predeterminado es Error, porque eso es lo que la mayoría de los usuarios esperan.

ts
const { error } = useQuery({ queryKey: ['groups'], queryFn: fetchGroups })
//      ^? const error: Error

typescript playground

ts
const { error } = useQuery({ queryKey: ['groups'], queryFn: fetchGroups })
//      ^? const error: Ref<unknown>

if (error.value instanceof Error) {
  error.value
  //     ^? const error: Error
}

typescript playground

ts
const { error } = useQuery<Group[], string>(['groups'], fetchGroups)
//      ^? const error: string | null
ts
import axios from 'axios'

const { error } = useQuery({ queryKey: ['groups'], queryFn: fetchGroups })
//      ^? const error: Error | null

if (axios.isAxiosError(error)) {
  error
  // ^? const error: AxiosError
}

typescript playground

ts
import '@tanstack/vue-query'

declare module '@tanstack/vue-query' {
  interface Register {
    defaultError: AxiosError
  }
}

const { error } = useQuery({ queryKey: ['groups'], queryFn: fetchGroups })
//      ^? const error: AxiosError | null

Tipar meta Registrar Meta global

De manera similar a registrar un tipo de error global, también puede registrar un tipo Meta global. Esto garantiza que el campo meta opcional sobre consultas y mutaciones se mantenga coherente y tenga seguridad de escritura. Tenga en cuenta que el tipo registrado debe extender Record<string, unknown> para que meta siga siendo un objeto.

ts
import '@tanstack/vue-query'

interface MyMeta extends Record<string, unknown> {
  // Your meta type definition.
}

declare module '@tanstack/vue-query' {
  interface Register {
    queryMeta: MyMeta
    mutationMeta: MyMeta
  }
}

Tipar Opciones de Consultas

Si integra opciones de consulta en useQuery, obtendrá una inferencia de tipos automática. Sin embargo, es posible que desee extraer las opciones de consulta en una función separada para compartirlas entre useQuery y por ejemplo prefetchQuery. En ese caso, perderías la inferencia de tipos. Para recuperarlo, puede utilizar el asistente queryOptions:

ts
import { queryOptions } from '@tanstack/vue-query'

function groupOptions() {
  return queryOptions({
    queryKey: ['groups'],
    queryFn: fetchGroups,
    staleTime: 5 * 1000,
  })
}

useQuery(groupOptions())
queryClient.prefetchQuery(groupOptions())

Además, la queryKey devuelta por queryOptions conoce la queryFn asociada a ella y podemos aprovechar esa información de tipo para que funciones como queryClient.getQueryData también tengan en cuenta esos tipos:

ts
function groupOptions() {
  return queryOptions({
    queryKey: ['groups'],
    queryFn: fetchGroups,
    staleTime: 5 * 1000,
  })
}

const data = queryClient.getQueryData(groupOptions().queryKey)
//     ^? const data: Group[] | undefined

Sin queryOptions, el tipo de data sería unknown, a menos que le pasáramos un genérico:

ts
const data = queryClient.getQueryData<Group[]>(['groups'])

Otras Lecturas

Para obtener consejos y trucos sobre la inferencia de tipos, consulte Vue Query y TypeScript en los recursos de la comunidad. Para saber cómo obtener la mejor seguridad de tipos posible, puede leer Vue Query con Tipos-seguros.

Desactivación segura de consultas mediante skipToken

Si está utilizando TypeScript, puede utilizar skipToken para deshabilitar una consulta. Esto es útil cuando desea deshabilitar una consulta basada en una condición, pero aún desea mantener la consulta segura. Lea más al respecto en la guía Desactivación de Consultas.