Framework
Version

TypeScript

Solid Query ist in TypeScript geschrieben, um sicherzustellen, dass die Bibliothek und Ihre Projekte typsicher sind!

Zu beachtende Punkte

  • Typen erfordern derzeit die Verwendung von TypeScript v4.7 oder höher
  • Änderungen an Typen in diesem Repository gelten als nicht-brechend und werden normalerweise als Patch-Semver-Änderungen veröffentlicht (andernfalls wäre jede Typverbesserung eine Hauptversion!).
  • Es wird dringend empfohlen, die Version Ihres solid-query-Pakets auf eine bestimmte Patch-Version zu sperren und mit der Erwartung eines Upgrades fortzufahren, dass Typen zwischen beliebigen Releases behoben oder aktualisiert werden können
  • Die nicht typbezogene öffentliche API von Solid Query folgt Semver weiterhin sehr streng.

Typinferenzen

Typen in Solid Query fließen im Allgemeinen sehr gut durch, sodass Sie keine Typannotationen für sich selbst bereitstellen müssen

tsx
import { useQuery } from '@tanstack/solid-query'

const query = useQuery(() => ({
  queryKey: ['number'],
  queryFn: () => Promise.resolve(5),
}))

query.data
//    ^? (property) data: number | undefined
import { useQuery } from '@tanstack/solid-query'

const query = useQuery(() => ({
  queryKey: ['number'],
  queryFn: () => Promise.resolve(5),
}))

query.data
//    ^? (property) data: number | undefined

typescript playground

tsx
import { useQuery } from '@tanstack/solid-query'

const query = useQuery(() => ({
  queryKey: ['test'],
  queryFn: () => Promise.resolve(5),
  select: (data) => data.toString(),
}))

query.data
//    ^? (property) data: string | undefined
import { useQuery } from '@tanstack/solid-query'

const query = useQuery(() => ({
  queryKey: ['test'],
  queryFn: () => Promise.resolve(5),
  select: (data) => data.toString(),
}))

query.data
//    ^? (property) data: string | undefined

typescript playground

Dies funktioniert am besten, wenn Ihre queryFn einen klar definierten Rückgabetyp hat. Beachten Sie, dass die meisten Datenabrufbibliotheken standardmäßig any zurückgeben, stellen Sie also sicher, dass Sie sie in eine ordnungsgemäß typisierte Funktion extrahieren

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

const query = useQuery(() => ({
  queryKey: ['groups'],
  queryFn: fetchGroups,
}))

query.data
//    ^? (property) data: Group[] | undefined
const fetchGroups = (): Promise<Group[]> =>
  axios.get('/groups').then((response) => response.data)

const query = useQuery(() => ({
  queryKey: ['groups'],
  queryFn: fetchGroups,
}))

query.data
//    ^? (property) data: Group[] | undefined

typescript playground

Typ-Verengung

Solid Query verwendet einen diskriminierten Union-Typ für das Query-Ergebnis, der durch das Feld status und die abgeleiteten booleschen Statusflags diskriminiert wird. Dies ermöglicht es Ihnen, z. B. den success-Status zu prüfen, um data als definiert zu kennzeichnen

tsx
const query = useQuery(() => ({
  queryKey: ['number'],
  queryFn: () => Promise.resolve(5),
}))

if (query.isSuccess) {
  const data = query.data
  //     ^? const data: number
}
const query = useQuery(() => ({
  queryKey: ['number'],
  queryFn: () => Promise.resolve(5),
}))

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

typescript playground

Typisierung des Fehlerfelds

Der Typ für Fehler ist standardmäßig Error, da dies das ist, was die meisten Benutzer erwarten.

tsx
const query = useQuery(() => ({
  queryKey: ['groups'],
  queryFn: fetchGroups,
}))

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

query.error
//    ^? (property) error: Error | null

typescript playground

Wenn Sie einen benutzerdefinierten Fehler oder etwas werfen möchten, das kein Error ist, können Sie den Typ des Fehlerfelds angeben

tsx
const query = useQuery<Group[], string>(() => ({
  queryKey: ['groups'],
  queryFn: fetchGroups,
}))

query.error
//    ^? (property) error: string | null
const query = useQuery<Group[], string>(() => ({
  queryKey: ['groups'],
  queryFn: fetchGroups,
}))

query.error
//    ^? (property) error: string | null

Dies hat jedoch den Nachteil, dass die Typinferenz für alle anderen Generika von useQuery nicht mehr funktioniert. Es gilt im Allgemeinen nicht als gute Praxis, etwas anderes als einen Error auszulösen. Wenn Sie also eine Unterklasse wie AxiosError haben, können Sie Typ-Narrowing verwenden, um das Fehlerfeld spezifischer zu machen.

tsx
import axios from 'axios'

const query = useQuery(() => ({
  queryKey: ['groups'],
  queryFn: fetchGroups,
}))

query.error
//    ^? (property) error: Error | null

if (axios.isAxiosError(query.error)) {
  query.error
  //    ^? (property) error: AxiosError
}
import axios from 'axios'

const query = useQuery(() => ({
  queryKey: ['groups'],
  queryFn: fetchGroups,
}))

query.error
//    ^? (property) error: Error | null

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

typescript playground

tsx
import '@tanstack/solid-query'

declare module '@tanstack/solid-query' {
  interface Register {
    // Use unknown so call sites must narrow explicitly.
    defaultError: unknown
  }
}

const query = useQuery(() => ({
  queryKey: ['groups'],
  queryFn: fetchGroups,
}))

query.error
//    ^? (property) error: unknown | null
import '@tanstack/solid-query'

declare module '@tanstack/solid-query' {
  interface Register {
    // Use unknown so call sites must narrow explicitly.
    defaultError: unknown
  }
}

const query = useQuery(() => ({
  queryKey: ['groups'],
  queryFn: fetchGroups,
}))

query.error
//    ^? (property) error: unknown | null

Registrierung des globalen Meta

Ähnlich wie bei der Registrierung eines globalen Fehlertyps können Sie auch einen globalen Meta-Typ registrieren. Dies stellt sicher, dass das optionale Feld meta bei Queries und Mutationen konsistent und typsicher bleibt. Beachten Sie, dass der registrierte Typ von Record<string, unknown> erben muss, damit meta ein Objekt bleibt.

ts
import '@tanstack/solid-query'

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

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

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

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

Typisierung von Query-Optionen

Wenn Sie Query-Optionen direkt in useQuery einfügen, erhalten Sie automatische Typschätzung. Möglicherweise möchten Sie die Query-Optionen jedoch in eine separate Funktion extrahieren, um sie zwischen useQuery und z. B. prefetchQuery zu teilen. In diesem Fall würden Sie die Typschätzung verlieren. Um sie wiederzugewinnen, können Sie den Helfer queryOptions verwenden

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

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

useQuery(groupOptions)
queryClient.prefetchQuery(groupOptions())
import { queryOptions } from '@tanstack/solid-query'

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

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

Darüber hinaus kennt der von queryOptions zurückgegebene queryKey die zugehörige queryFn, und wir können diese Typinformationen nutzen, um Funktionen wie queryClient.getQueryData ebenfalls typsicher zu machen

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

const data = queryClient.getQueryData(groupOptions().queryKey)
//    ^? const data: Group[] | undefined
function groupOptions() {
  return queryOptions({
    queryKey: ['groups'],
    queryFn: fetchGroups,
    staleTime: 5 * 1000,
  })
}

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

Ohne queryOptions wäre der Typ von data unknown, es sei denn, wir würden ihm ein generisches Element übergeben

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

Typsicheres Deaktivieren von Abfragen mit skipToken

Wenn Sie TypeScript verwenden, können Sie skipToken verwenden, um eine Abfrage zu deaktivieren. Dies ist nützlich, wenn Sie eine Abfrage basierend auf einer Bedingung deaktivieren möchten, aber die Abfrage trotzdem typsicher halten möchten.

Lesen Sie mehr darüber im Leitfaden Disabling Queries.