2 votes

Typescript utilisation dynamique de useReducer

Je suis en train de créer un hook réutilisable useReducer avec des typings.

Voici mon code actuel :

type State = {
  data?: T
  isLoading: boolean
  error?: string
}

type Action =
  | { type: "request" }
  | { type: "success"; results: T }
  | { type: "failure"; error: string }

function reducer(state: State, action: Action): State {
  switch (action.type) {
    case "request":
      return { isLoading: true }
    case "success":
      return { isLoading: false, data: action.results }
    case "failure":
      return { isLoading: false, error: action.error }
  }
}

export function useFetchState() {
 return useReducer(reducer, {isLoading: false});
}

Comme vous pouvez le voir, le hook devrait être utilisé pour contenir l'état de la requête mais les données doivent être dynamiques, de sorte qu'elles puissent être utilisées dans différents contextes :

const [videoFetch, dispatchVideo] = useFetchState()
const [userFetch, dispatchUser] = useFetchState()

Mon problème est que l'expression reducer échoue en raison de Erreur:(26, 20) TS2345: Argument de type 'boolean' n'est pas assignable à un paramètre de type 'Reducer'., mais sans spécifier T, le type de données est inconnu.

Je ne suis pas sûr de ce que cette situation est appelée dans le monde TypeScript, donc j'espère que quelqu'un peut m'expliquer si et comment je peux atteindre ce que je veux.

Je vous remercie beaucoup.

5voto

Colliot Points 604

reducer n'est pas grammaticalement incorrect. reducer est simplement reducer. Il n'y a pas de tel chose comme reducer. Le compilateur l'interprète comme reducer < T > (opérateurs de comparaison), qu'il pense être probablement une valeur booléenne une fois complétée en tant qu'expression. C'est pourquoi il se plaint "L'argument de type boolean n'est pas assignable au paramètre de type Reducer" -- le compilateur détecte une valeur booléenne, ou une valeur soupçonnée d'être booléenne, à l'endroit où une valeur de type Reducer (qui est simplement votre variable reducer) devrait apparaître.

Ne pas passer le paramètre générique est également incorrect. L'inférence de type de, par exemple, videoFetch serait erronée: videoFetch est déduit comme State<{}> (probablement State dans les versions plus récentes. Je ne suis pas sûr à 100% de cela cependant).

Alors où devrait donc se trouver le paramètre générique T en réalité? Notez que l'inférence de type se produit en fait sur useReducer. Nous devons donc simplement fournir manuellement les bons paramètres de type de useReducer:

export function useFetchState() {
  return useReducer, Action>>(reducer, { isLoading: false });
}

Dans ce cas, vous pouvez vérifier que le type de videoFetch est correctement inféré. De même que les types de toutes les autres variables.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X