A collection of JSON data containing various diverse values

My classes are not specific and they look like this:

type SyncReducerAction<TState> = (state: TState, ...args: any[]) => TState;

type AsyncReducerAction<TState, TResult, TRest extends any[]> = {
  promise: (...args: TRest) => Promise<TResult>;
  pending?: (state: TState, ...args: TRest) => TState;
  fullfilled: (state: TState, result: TResult, ...args: TRest) => TState;
  rejected: (state: TState, error: Error, ...args: TRest) => TState;
};

I am trying to create a JSON object where the value can be one of these two types. Here is a function that should accept this object:

function get<
  T extends {
    [K in keyof T]: T[keyof T] extends SyncReducerAction<any>
      ? SyncReducerAction<Parameters<T[keyof T]>[0]>
      : T[keyof T] extends AsyncReducerAction<
          infer TState,
          infer TResult,
          infer TRest
        >
      ? AsyncReducerAction<TState, TResult, TRest>
      : never;
  }
>(input: T): ReducersToActions<T> {
  throw new Error("Not implemented");
}

However, this does not seem to work. Using only one type works fine.

TypeScript Playground link

Edit:

This version almost gets it right, but the types are still incorrect: Playground link. Removing TResult from AsyncReducerAction and setting it to any seems to make it work.

Answer №1

The great news is that the solution is much simpler than what you've imagined. Despite all the infer and extends complexity in the generic get, they actually have no impact. Each property's TRest is unique and not accessible outside of this context.

All you need to do is define your generic T as a map object where each value is either a synchronous or asynchronous reducer.

function get<
  T extends {
    [K in keyof T]: SyncReducerAction<any> | AsyncReducerAction<any, any, any>
  }
>(input: T): ReducersToActions<T> {
  throw new Error("Not implemented");
}

By doing this, all errors disappear except for one line with a never function argument.

fulfilled: (state: CounterType, result: never) => state,

You should change it to:

fulfilled: (state: CounterType) => state,

After making this adjustment, everything should work perfectly!

I'm able to properly infer all action creators, so your ReducersToActions<T> seems to be in good shape.

Playground Link

Answer №2

For the ultimate solution, check out this resource: Typescript Playground

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

Generating instances using TypeScript generics

Looking to create a factory for instantiating classes with generics. After checking out the TypeScript docs, everything seems to work as expected. Here's a simplified version of how it can be done: class Person { firstName = 'John'; ...

Function that sets object properties based on specified keys and verifies the value

Let's consider a scenario where we have an object structured like this: interface Test{ a: number; b: string; c: boolean; } const obj:Test = { a: 1, b: '1', c: true, } We aim to create a function that can modify the value ...

Enhanced Autocomplete Feature with Select All Option in MUI

Currently, I am utilizing Material UI (5) and the Autocomplete component with the option for multiselect enabled. In addition, I am implementing the "checkbox" customization as per the MUI documentation. To enhance this further, I am attempting to incorpor ...

What are the differences between an optional property and a non-optional property?

Let's say I am working on creating an array of type CoolObject. What would be the better approach if some objects have the property format, while others do not? // Option 1 export interface CoolObject { name: string; color: string; ...

Custom Joi middleware in Express v4 is failing to pass the Request, Response, and Next objects

I am currently in the process of developing a unique middleware function to work with Joi that will be placed on my routes for validating a Joi schema. In the past, I have created middlewares for JWT validation without passing any parameters, and they wor ...

Starting the process of configuring Angular 5 with Express using TypeScript

Hi there! I am looking to create a fresh application using angular 5 and express (typescript for express as well). Do you have any helpful guides or tips that could assist me in reaching my objective? Appreciate all the help, Giuseppe ...

What is the best way to verify if the ReactDOM.render method has been invoked with a React component as an argument

Here's the code snippet: index.tsx: import React, { Component } from 'react'; import ReactDOM from 'react-dom'; export function Loading(props) { return <div {...props}>loading...</div>; } export class MyComponent e ...

The comparison between "rxjs-tslint" and "rxjs-tslint-rules" npm packages

Previously, I utilized the rxjs-tslint-rules package to identify RxJS-related issues in my projects. This package was included in the devDependencies section of my projects' package.json files. Now, there is a new rxjs-tslint package that introduces ...

In which situations is it required to specify the return type of a function in TypeScript?

When it comes to making functions in typescript, the language can often infer the return type automatically. Take for instance this basic function: function calculateProduct(x: number, y: number) { return x * y; } However, there are scenarios where dec ...

Placing a MongoDB query results in an increase of roughly 120MB in the total JS heap size

I'm puzzled by the fact that the heap size increases when I include a MongoDB database query in a function within my controller. Here is the code for my router: import { Router } from "express"; import profileController from '../contro ...

Encountered an error trying to access properties that are undefined while working with Ionic Angular, specifically having trouble reading the 'update

As someone who is new to building ionic angular applications (coming from a PHP background), I am currently facing an issue. I have a page with the following code: export class LicencesTabPage implements OnInit { public licencesData: any[] | void; co ...

Learn the process of extracting an array of objects by utilizing an interface

Working with an array of objects containing a large amount of data can be challenging. Here's an example dataset with multiple key-value pairs: [{ "id": 1, "name":"name1", age: 11, "skl": {"name": & ...

Errors may occur when utilizing TypeScript with the Context Provider API in React

I am in the process of developing a theme changer feature and I want to save the color chosen by the user in the context. However, when I try to pass data to the value prop of the Context.Provider, I encounter an error message TS2739: Type 'Readonly&l ...

Will a JavaScript source map file continue to function properly even after the source code file has been minified?

My experience I specialize in utilizing TypeScript and Visual Studio to transform highly organized code into functional JavaScript. My skills involve configuring the project and Visual Studio to perform various tasks: Merging multiple compiled JavaScrip ...

Exploring the Worldwide Influence of TypeScript, React, and Material-UI

I am currently following an official tutorial on creating a global theme for my app. In my root component, I am setting up the global theme like this: const themeInstance = { backgroundColor: 'cadetblue' } render ( <ThemeProvider theme ...

Angular 7 ESRI loader search widget focus out bug: finding a solution

I am currently working on implementing an ESRI map using esri-loader in my Angular application. Everything seems to be working fine, but I am encountering an error when typing something into the search widget and then focusing out of it. "Uncaught Typ ...

What does the "start" script do in the package.json file for Angular 2 when running "concurrent "npm run tsc:w" "npm run lite"" command?

What is the purpose of concurrent in this code snippet? "scripts": { "tsc": "tsc", "tsc:w": "tsc -w", "lite": "lite-server", "start": "Concurrent npm run tsc:w npm run lite" } ...

After defining the NEXTAUTH_URL and NEXTAUTH_SECRET variables, the getServerSession(authOptions) function in NextJS is returning null

I've been attempting to set up OAuth with the Google provider for my Next.js 13 web application. Unfortunately, I'm encountering an issue where getServerSession(authOptions) is returning null. Despite trying various solutions such as setting NEXT ...

Nuxt SSR encounters issues when modifying data variables

There is an issue with my Nuxt app where sometimes when the page loads, I encounter an error in the console that causes the page to stop loading other components. The error message reads: Cannot read properties of undefined (reading 'resolved') ...

Vue: Simple ways to retrieve state data in MutationAction

I'm having trouble accessing the state inside @MutationAction Here is the setup I am using: Nuxt.js v2.13.3 "vuex-module-decorators": "^0.17.0" import { Module, VuexModule, MutationAction } from 'vuex-module-decorators' ...