Creating a typescript type for contextual dispatch by leveraging the values of another interface

I am seeking to define a specific type for my "reducer" function.

The "reducer" function I have takes in 2 parameters: the current state and the data sent in the dispatch context (to be used by the reducer).

const reducer = (
    state: any,
    props: {
        action: string,
       value: any,
    } 
) => {
...
}

The second parameter will always be an object with 2 properties: action and value.

However, I am not comfortable allowing just any value for the "value" property. Hence, I wish to create a dynamic "type".

I already have an interface containing all the information present in my context.

DefaultValueContextInterface interface {
    floatMsgError: string;
    isOpenSidebar: boolean;
    .....
}

What I aim for is that this new "type" I want to establish only permits something like:

{
    action: "floatMsgError",
    value: string,
} 

Why restrict "value" to only "string"? Because in the interface "DefaultValueContextInterface", the property "floatMsgError" is of type string. Similarly, each property in the "DefaultValueContextInterface" interface follows the same pattern automatically. If the value for "action" passed to the "reducer" function matches "isOpenSidebar", then the corresponding "value" must be of type boolean.

I could manually create the type like so:

{
    action: "floatMsgError",
    value: string,
} 
| {
    action: "isOpenSidebar",
    value: boolean,
}

However, having numerous properties within my context makes manual creation impractical.

I also attempted using "[P in keyof DefaultValueContextInterface]" but was only able to combine it as follows:

type Props = {
    [P in keyof DefaultValueContextInterface]: {
        action: P;
        value: DefaultValueContextInterface[P];
    };
};

This doesn't suit my needs because it generates an object which isn't the desired outcome. Nonetheless, the nested objects do align closely with what I require. I just need to figure out a different looping mechanism to achieve it.

At present, I have this:

type Props = {
  action: keyof DefaultValueContextInterface;
  value: DefaultValueContextInterface[keyof DefaultValueContextInterface];
};

However, this does not effectively link the values of "action" and "value" together :/

Answer №1

Your method of using a mapped type is almost correct. To fully implement it, you just need to create a union by indexing the type with

keyof DefaultValueContextInterface
.

interface DefaultValueContextInterface {
    floatMsgError: string
    isOpenSidebar: boolean
}

type Props = {
    [P in keyof DefaultValueContextInterface]: {
        action: P
        value: DefaultValueContextInterface[P]
    }
}[keyof DefaultValueContextInterface]

Interactive 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

`I'm having difficulty transferring the project to Typescript paths`

I posted a question earlier today about using paths in TypeScript. Now I'm attempting to apply this specific project utilizing that method. My first step is cloning it: git clone <a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cf ...

The React component continuously refreshes whenever the screen is resized or a different tab is opened

I've encountered a bizarre issue on my portfolio site where a diagonal circle is generated every few seconds. The problem arises when I minimize the window or switch tabs, and upon returning, multiple circles populate the screen simultaneously. This b ...

Error encountered: No matching overload found for MUI styled TypeScript

I am encountering an issue: No overload matches this call. Looking for a solution to fix this problem. I am attempting to design a customized button. While I have successfully created the button, I am facing the aforementioned error. Below is my code ...

After utilizing the d3-scale function to declare an object, my developer visual suddenly ceases to function

Upon completing a section of a Power BI tutorial, the developer encountered a visual that displayed nothing but a blank page (despite running correctly). Unable to pinpoint the issue, debugging was initiated. The following test code snippet for debugging w ...

Generating images with HTML canvas only occurs once before stopping

I successfully implemented an image generation button using Nextjs and the HTML canvas element. The functionality works almost flawlessly - when a user clicks the "Generate Image" button, it creates an image containing smaller images with labels underneath ...

Upon the initial loading of GoJS and Angular Links, nodes are not bypassed

Hey there, I'm currently working on a workflow editor and renderer using Angular and GoJS. Everything seems to be in order, except for this one pesky bug that's bothering me. When the page first loads, the links don't avoid nodes properly. H ...

Creating a cohesive "notification" feature in React with TypeScript that is integrated with one specific component

I am currently working on designing my application to streamline all notifications through a single "snackbar" style component (utilizing the material UI snackbar component) that encompasses the entire app: For instance class App extends React.Component ...

Showing Arrays in Angular on HTML Page

I have created an array that stores multiple arrays with 3 indexes each. An example of the structure looks like this: (3) [Array(3), Array(3), Array(3)] 0: (3) [199.4, 10.5, 19] 1: (3) [47.2, 2.1, 23] 2: (3) [133.6, 5.3, 25] In my HTML, I want to display ...

Customize buttons in Material UI using the styled component API provided by MUI

I am intrigued by the Material UI Styled Component API, not to be confused with the styled-component library. However, I am facing difficulty in converting my simple button component into a linked button. Can anyone advise me on how to incorporate a react ...

Error message: Unable to instantiate cp in Angular 17 application while building with npm run in docker container

After creating a Dockerfile to containerize my application, I encountered an issue. When I set ng serve as the entrypoint in the Dockerfile, everything works fine. However, the problem arises when I try to execute npm run build. Below is the content of my ...

Issues with naming in Gulp, Angular2 Final, and Visual Studio: "Cannot find name" and "Duplicate identifier" errors

Recently, I updated my project to utilize the final release of Angular 2 and also upgraded Visual Studio to use TypeScript 2.0.3 from the Tool -> Extensions and Updates manager. I compile my TypeScript using Gulp, and it compiles without any errors. Howev ...

Instructions for enabling the touch slider feature in the Igx carousel component with Angular 6 or higher

Looking to enable the touch slider for Igx carousel using angular 6+? I am trying to implement the igx carousel for image sliding with reference from a stackblitz demo (https://stackblitz.com/edit/github-j6q6ad?file=src%2Fapp%2Fcarousel%2Fcarousel.compone ...

You have encountered an issue with the runtime-only build of Vue, which does not include the template compiler

Lately, I have been utilizing Vue in a project and encountered an issue where upon compiling, my browser page displays as white with an error message stating "You are using the runtime-only build of Vue where the template compiler is not available. Either ...

Design a TypeScript interface inspired by a set static array

I am working with an array of predefined strings and I need to create an interface based on them. To illustrate, here is an example of pseudo-interfaces: const options = ["option1", "option2", "option3"]; interface Selection { choice: keyof options; ...

Dealing with numerous dynamically generated tables while incorporating sorting in Angular: a comprehensive guide

I am faced with a challenge involving multiple dynamically created Angular tables, each containing the same columns but different data. The issue at hand is sorting the columns in each table separately. At present, I have two tables set up. On clicking the ...

Retrieving the return type of generic functions stored in a map

In this unique scenario, I have a dictionary with polymorphic functions that accept the same argument but return different results: const dict = { one: { foo<A>(a: A) { return [a] as const } }, two: { foo<A>(a: A) { ...

Selecting a filter for an array of objects

I'm struggling to implement a search feature in my mat-select DropDown. The existing options I've found online aren't quite working for me due to the object array I am passing to the Dropdown. Any assistance or guidance on this matter would ...

Incorporating an external SVG file into an Angular project and enhancing a particular SVG element within the SVG with an Angular Material Tooltip, all from a TypeScript file

Parts of the angular code that are specific |SVG File| <svg version="1.0" xmlns="http://www.w3.org/2000/svg" width="950" height="450" viewBox="0 0 1280.000000 1119.000000" preserveAspectRatio= ...

The error you are seeing is a result of your application code and not generated by Cypress

I attempted to test the following simple code snippet: type Website = string; it('loads examples', () => { const website: Website = 'https://www.ebay.com/'; cy.visit(website); cy.get('input[type="text"]').type(& ...

Similar to the getState() function in react-redux, ngrx provides a similar method in Angular 6 with ngrx 6

Recently, I developed an application with react and redux where I used the getState() method to retrieve the state of the store and extract a specific slice using destructuring. Here's an example: const { user } = getState(); Now, I am transitioning ...