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

Utilizing Angular to import an SVG file from a backend and incorporate its content as a template

I am looking for a solution to load an SVG date from my Spring Boot backend and utilize it as an Angular template. Currently, the request is structured like this: getSVG (): Observable <any> { return this.http.get(`${environment.apiUrl}/path ...

`Is there a way to effectively test an @Input component in Angular?`

Despite multiple successful attempts in the past, I am facing some difficulty getting this to function properly. Within my component, I have an input @Input data: Data, which is used in my template to conditionally display certain content. Oddly enough, du ...

What could be causing my function to return as undefined the second time it's invoked?

Within my approach private onDataLoadSuccessful(users: User[], roles: Role[]) { this.alertService.stopLoadingMessage(); this.loadingIndicator = false; this.dataSource.data = users.map(data => { let newData: User; newData = ...

Stop Node Modules from Referencing Global Location

Recently, I ran into an issue after updating my project from Git. The problem arose when trying to use ngx-material-timepicker in conjunction with the luxon library. (It's important to note that ngx-material-timepicker isn't a new addition to th ...

Unable to load dynamic data in Angular 2 smart table

Currently, I am utilizing Angular 6 along with smart table by visiting this link: . Everything was functioning smoothly, until the moment I attempted to switch from static to dynamic data: The following code works perfectly and displays all the content ...

Encountering an XHR error when using a systemjs module in TypeScript

Error: GET http://localhost:63342/Dog.js 404 (Not Found) XHR error (404 Not Found) loading http://localhost:63342/Dog.js <br/><br/>Below is the script in my index.html file. ...

The CastError occurred because the attempt to add a string value to an array failed when converting it to a string

An issue I am encountering: *CastError: Cast to string failed for value "[ 'ZTM', 'NASA' ]" (type Array) at path "customers" at model.Query.exec (/Users/mike/Documents/NodeJS-applications/NASA-project/server/node_modules/mongoose/lib/qu ...

React's Material-UI ToggleButtonGroup offers a seamless way

I'm having trouble getting the ToggleButton selected property from material ui to function properly with ToggleButton. I followed the Material Ui documentation and created a StyledToggleButton as shown below: const StyledToggleButton = withStyles({ ...

How can we determine the props' type specific to each component?

type ComponentCProps = { c: string; }; function ComponentC(props: ComponentCProps) { return <div>component C</div>; } type ComponentDProps = { d: string; }; function ComponentD(props: ComponentDProps) { return <div>component D& ...

Learning to handle data fetching and looping in NextJs

I'm facing an issue with fetching data through a loop in getStaticProps. The array ends up empty due to asynchronous code. If I pass the ID array and implement the logic within the React component, it works fine. Should I continue using the component ...

Discovering the optimum route within a 2D array given specific limitations using Dynamic Programming

Hey, I have a query related to dynamic programming (dp) that goes like this: Input: A 2D array of numbers Output: The maximum sum of a path from (0,0) to (n-1,n-1) with the following conditions: You can only move down and right i.e. from (A[i-1][j]) t ...

Encountering issues when trying to import const enums in a webpack project using babel

Currently, I am working on a react project that was initially created using create-react-app. However, we later ejected and made extensive modifications to the webpack configuration. My current struggle lies in importing const enums from external libraries ...

Can TypeScript automatically deduce keys from a changing object structure?

My goal here is to implement intellisense/autocomplete for an object created from an array, similar to an Action Creator for Redux. The array consists of strings (string[]) that can be transformed into an object with a specific shape { [string]: string }. ...

When I receive a 404 response from the API, I aim to start my observable

How can I trigger my observable initialization when receiving a 404 response from the API? The code snippet below is not working as expected. const urlParams = { email: this.email }; this.voicesProfileObservable$ = this.service.request<any>( AVAI ...

Utilizing moment.js in conjunction with typescript and the module setting of "amd"

Attempting to utilize moment.js with TypeScript 2.1.5 has been a bit of a challenge for me. I went ahead and installed moment using npm : npm install moment --save-dev The d.ts file is already included with moment.js, so no need to install via @typings ...

The call to react.cloneElement does not match any overloads

I'm encountering a typescript error in my React code when using React.cloneElement with the first parameter "children", and I am unsure of how to resolve it. As a newcomer to typescript, I believe that the type definitions in index.d.ts for cloneElem ...

$(...).parentElement is not a function - Troubleshooting a Problem with WebDriver IO and TypeScript

Alright, the objective is simple. I need to ascend from the root to obtain its parent element. Following the webdriver documentation, it should resemble something like this: it('should retrieve the class from the parent element', async () => { ...

Error message: Property is not found in the $rootScope object in AngularJS

Encountering an issue while attempting to assign a value to the rootscope in Typescript. class TestClass{ this.rootScope: ng.IRootScopeService; constructor($rootScope){ this.rootScope = $rootScope; } addValueToRoot=()=>{ ...

Locate and retrieve the item that appears most often in a given array

In order to determine the mode of an array consisting of integer numbers only, I must create a function named findMode. If the array is empty, the function should return 0. Otherwise, it should return the element that occurs most frequently in the array. I ...

What is the best way to calculate the total sum of dynamically changing inputs in Angular 2?

Is there a way to calculate the total sum from dynamic inputs in angular 2? I'm not sure how to implement this. Thanks! //html component <md-input-container style="width: 80px;"> <input md-input class="debit" formControlNam ...