Dynamic useReducer in Typescript allows for flexible state management by

Currently working on developing a reusable useReducer hook with typings.

Below is the existing code:

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

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

function reducer<T>(state: State<T>, action: Action<T>): State<T> {
  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<T>() {
 return useReducer(reducer<T>, {isLoading: false});
}

The purpose of this hook is to handle fetch state while allowing for dynamic data, making it versatile for various contexts:

const [videoFetch, dispatchVideo] = useFetchState<Video[]>()
const [userFetch, dispatchUser] = useFetchState<User[]>()

An issue arises where the expression reducer<T> throws an error stating Error:(26, 20) TS2345: Argument of type 'boolean' is not assignable to parameter of type 'Reducer'., yet excluding T leaves the data type unknown.

I would appreciate any insights on how to address this situation in TypeScript and achieve my desired outcome.

Thank you for your assistance.

Answer №1

reducer<T> is not considered grammatically incorrect. It should simply be reducer. There is no existence of a construct like reducer<T>. The compiler interprets it as reducer < T > (comparison operators), assuming it to be a boolean value when used in an expression. This results in the error message "Argument of type boolean is not assignable to parameter of type Reducer", indicating that where a value of type Reducer (in this case, your reducer variable) is expected, a boolean value or suspect boolean value was encountered.

However, omitting the generic parameter is also incorrect. For instance, without specifying the generic type for videoFetch, its type inference might be inaccurate: it may be inferred as State<{}> (potentially State<unknown> in newer versions, although not confirmed).

So where should the generic parameter T actually go? Type inference occurs within useReducer, so providing the correct type parameters for useReducer manually is necessary:

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

By following this approach, you can verify that the types of videoFetch and other variables are correctly inferred.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Can passing undefined to React's setState method be considered incorrect?

Imagine having the following state declared in a React component: const [selectedUsers, setSelectedUsers] = useState<IUser['id'][]>(); This state is being used as the value for a third party HTML <select /> component from Ant Design. ...

"What could be causing my React Native app to build without any issues even though the TypeScript compiler is throwing

Recently, I decided to explore TypeScript in combination with Expo. I took the time to set up linter and formatter integrations like typescript-eslint to help me catch errors while coding. Periodically, I run npx tsc to ensure my code compiles correctly an ...

Attempting to grasp the concept of Thennables within the VSCode API. Can these TypeScript code examples be considered equivalent?

I'm looking to perform a series of modifications on a document using the VSCode API. The key function in this process is Workspace.applyEdit, which gives back a Thennable. This is my first encounter with it, and the one returned from this function doe ...

After converting TypeScript to JavaScript, the import functionality appears to be malfunctioning

homepage.ts export function homepage () {...rest of function} app.ts import { homepage } from "./homepage"; homepage(); index.html <script src="/dist/app.js" type="text/javascript"></script> Error: Uncaught Sy ...

Upcoming 13.4 Error: NEXT_REDIRECT detected in API routes

Here is the code snippet from my /app/api/auth/route.ts file: import { redirect } from 'next/navigation'; export async function GET(req: Request) { try { redirect('/dashboard'); } catch (error) { console.log(error); ...

Typescript failing to verify the data within an object being extended to fulfill a type

In my coding project, I have defined an initial interface called IThing, which serves as the base for several other interfaces such as IThingA, IThingB, and more. interface IThing{ id: string; } interface IThingA extends IThing{ a1: string; a2 ...

Check out the computed typescript types

In my work with TypeScript types, I find myself frequently using Omit, Pick, and similar tools based on other types. While it generally gets the job done, I often struggle with readability when dealing with complex type manipulations. I am interested in f ...

IntelliSense in VSCode is unable to recognize the `exports` property within the package.json file

Currently, I am utilizing a library named sinuous, which contains a submodule known as "sinuous/map". Interestingly, VSCode seems to lack knowledge about the type of 'map' when using import { map } from "sinuous/map", but it recognizes the type ...

What steps should I follow to integrate the NextUI Tab component in my NextJS project?

Hi everyone, I am new to NextJS. I recently set up a basic NextJS starter project with NextUI by using the command npx create-next-app -e https://github.com/nextui-org/next-app-template. Now, I am trying to add a tab group with 3 tabs to the default page. ...

Error found in ngrx/effects with Typescript: the name used for a computed property must be associated with a predefined symbol

Currently diving into ngrx to set up an app state in my ionic 3.9.2 application (relying on this tutorial for guidance: ) Encountering an error while attempting to run the app: typescript: ...foo/bar/node_modules/@ngrx/effects/src/on_run_effects.d.ts, li ...

A TypeScript class transferring data to a different class

I have a set of class values that I need to store in another class. function retainValues(data1,data2){ this.first = data1; this.second = data2; } I am looking for a way to save these class values in a different class like this -> let other = N ...

Help with Material-UI: Passing unique props to a custom TreeItem component

I am trying to pass an argument category to the component CustomTreeItem which uses TreeItemContent. Documentation: https://mui.com/ru/api/tree-item/ import TreeItem, { TreeItemProps, useTreeItem, TreeItemContentProps, } from '@material-ui/lab ...

The JSX Configuration in TypeScript: Comparing ReactJSX and React

When working with Typescript and React, it's necessary to specify the jsx option in the compilerOptions section of the tsconfig.json file. Available values for this option include preserve, react, react-native, and react-jsx. { "compilerOptions": { ...

Node corrupting images during upload

I've been facing an issue with corrupted images when uploading them via Next.js API routes using Formidable. When submitting a form from my React component, I'm utilizing the following functions: const fileUpload = async (file: File) => ...

Angular Routing can be a powerful tool for managing multiple article posts in an efficient and organized way

I am in the process of building a website with Angular that features numerous articles. Whenever a user clicks on an article, I want it to navigate to a new URL using routing. To achieve this, I have created a new Article component and here is how my app- ...

Adding properties to React Component

Due to security reasons, I am required to update the ant design library in my codebase from version 3 to 4. In the past, this was how I used the icon: import { Icon } from 'antd'; const Demo = () => ( <div> <Icon type="smile" ...

Tips for creating a recursive string literal type in Typescript

I need to create a type that represents a series of numbers separated by ':' within a string. For example: '39:4893:30423', '232', '32:39' This is what I attempted: type N = `${number}` | '' type NL = `${ ...

What steps can be taken to stop Internet Explorer from caching Ajax requests in Angular2 using TypeScript?

Imagine a situation where a user has 10 points. When they click a button, an ajax call is made to the server to update the user's points after they have been used. The server should send back 9 points, which is functioning correctly on all browsers ex ...

Using React with Keycloak - Can only be initialized once

After encountering issues in my main application, I decided to create a new raw react project and follow the documentation to implement a simple keycloak login. The guide I used can be found here: https://github.com/react-keycloak/react-keycloak/blob/maste ...

Angular: How to Resolve Validation Error Messages

I have a TypeScript code block: dataxForm: fromGroup this.dataxForm = new FormGroup({ 'Description':new FormControl(null, Validaros.required}; 'Name':new FormControl(null, Validators.required}) Here is an HTML snippet: <mat-divider& ...