Is it possible to assign a property value to an object based on the type of another property?

In this illustrative example:

enum Methods {
    X = 'X',
    Y = 'Y'
}

type MethodProperties = {
    [Methods.X]: {
        x: string
    }
    [Methods.Y]: {
        y: string
    }
}

type Approach = {
    [method in keyof MethodProperties]: {
        method: method
    } & MethodProperties[method]
}

//produces the anticipated outcome, but may not be optimal for every scenario

const strategy1: Approach[Methods] = {
    method: Methods.X,
    x: 'string',
};

(() => {
    if (strategy1.method === Methods.X) {
        strategy1.x = 'anotherstring';
        //does not throw an error since the compiler recognizes
        //the potential properties based on method type
    }
})();

//does not generate the expected outcome, but might be more suitable for certain situations

type Plan = {
    method: Methods
    methodProps: MethodProperties[Plan['method']]
}

const strategy2: Plan = {
    method: Methods.X,
    methodProps: {
        x: 'string',
        y: 'string',
    }
};

(() => {
    if (strategy2.method === Methods.X) {
        strategy2.methodProps.x = 'anotherstring';
        //results in an error - Property 'x' does not exist on type '{ y: string; }'
    }
})();

Playground

The desired outcome is to notify the compiler that when state.type === ActionTypes.A, then the type of state.actionProps should be ActionProps[ActionTypes.A].

Are there any feasible workarounds for this issue?

Answer №1

Are you in search of a standard solution:

enum ActionTypes {
    A = 'A',
    B = 'B'
}

type ActionProps = {
    [ActionTypes.A]: {
        a: string
    }
    [ActionTypes.B]: {
        b: string
    }
}

type State<Type extends keyof ActionProps> = {
    type: Type
    actionProps: ActionProps[Type] & ActionProps[keyof ActionProps]
}

const state: State<ActionTypes.A> = {
    type: ActionTypes.A,
    actionProps: {
        a: 'string',
        b: 'string',
    }
};

(() => {
    if (state.type === ActionTypes.A) {
        state.actionProps.a = 'anotherstring';
        //errors - Property 'a' does not exist on type '{ b: string; }'
    }
})();

Yet, TypeScript appears unable to deduce the type parameter based on the .type property value, as this functionality is typically associated with discriminated unions.

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

Is there a way to trigger javascript on Amazon once the "Next Page" button is clicked?

My Greasemonkey script is designed to run on Amazon's search results page. However, I've noticed that when the "Next Page" button is clicked and new results are dynamically loaded, my script only executes once after the initial page load. Here&a ...

React Application Issue: Unable to successfully redirect to the homepage upon logging in

Attempting to create a web application with the MERN stack is causing some trouble when trying to redirect users to the home page post-login. Here's how it should ideally function: User inputs login details The server validates these details and gene ...

detect mouse click coordinates within an iframe that spans multiple domains

I am currently encountering an issue with tracking click position over a cross-domain iframe. Here is my current code: <div class="poin"> <iframe width="640" height="360" src="http://cross_domain" frameborder="0" allowfullscreen id="video">< ...

How can data be displayed in AngularJS/Json without using ng-repeat?

It seems like I am required to use ng-repeat in order to display the data, but I would prefer to avoid using it. angular: App.controller('aboutLongCtrl', function ($scope, $http) { $http.get('test_data/ar_org.json') .then(func ...

What is the best way to update a specific value in an object without affecting the rest of

Below is a data object: { name: "Catherine Myer", age: 23, birthday: "august" } If I want to pass this data as a prop to a component, but also change the age to 24, how can I do that? <NextPage data={author.age = 24}/> The ...

Extract content from whole webpage including HTML, CSS, and JavaScript

Currently I am working on developing a webpage version control backup/log system. The goal is to automatically save a static copy of the webpage, including all its CSS and JavaScript files, whenever there are any changes made. I have already figured out h ...

Utilizing Angular 9 with Jest for unit testing: simulating a promise, checking for method invocation afterwards

I'm in need of assistance as I am unsure how to mock a promise and verify that a method is called within the then() block. When I click on the save button of my form, my code appears as follows: // File: myComponent.ts save() { const myObject = n ...

What is the best method for saving console.log output to a file?

I have a tree structure containing objects: let tree = {id: 1, children: [{id: 2, children: [{id: 3}]}]} My goal is to save all the id values from this tree in a text file, indenting elements with children: 1 2 3 Currently, I am using the following ...

Froala Editor: Innovative external toolbar that pops up when the button is clicked

In our project, we are implementing the latest version of Froala and aim to configure it so that the toolbar is activated by a separate external button, similar to Gmail where the editor initially does not display a toolbar. I attempted to modify the &apo ...

In the useEffect hook, the context userdata initializes as an empty object

I am facing an issue with my code where the imported object is not being read by useEffect. The user object is imported from another context and when I try to use it in the useEffect of DataContext, it returns an empty object. I suspect that useEffect is b ...

Error: NullInjector - The injector encountered an error when trying to inject the Component into the MatDialogRef in the AppModule

When utilizing a component via routing as well as injecting it as the "target" of a modal dialog, I encountered an issue: export class Component1 implements OnInit { constructor(private service: <someService>, public dialogRef: MatDialogRef<Compo ...

What is the best way to extract multiple records from an Array?

Below is a simple filter function that filters Rec_pagedItems in an array called allItems. someval(value){ if(value.length>=5){ this._pagedItems= this.allItems.find(e=>e.uniqueid == value || e.name == value ); if(this._pagedItem ...

React Tour displays incorrect positions when coupled with Slide transitions in Material UI Dialog

Currently, I am utilizing the react-tour library to incorporate a guidance feature into my project. The issue arises in the initial step which involves a small component within a <Dialog /> that requires highlighting. However, due to a transition ef ...

Setting a checkbox to true within the MUI Data Grid using my input onChange event - how can I achieve this?

I am looking to highlight the selected row in my usage input onChange event. https://i.stack.imgur.com/rp9rW.png Details of Columns: const columns = [ { field: 'part_code', headerName: 'Part Code', width: 200 }, { ...

Leveraging Vue properties within CSS styling

I am looking to utilize Vue data/prop variables within the <style> tag located at the bottom of my component. For example, suppose I have a component structured like this: <template> <div class="cl"></div> </template> < ...

In search of inspiration to create a recipient list similar to Gmail using Vue3?

Recently, I've been trying to create a recipient list similar to that in Gmail using Vue3 but I'm stuck and unable to find helpful resources online. recipient list I have an array of email addresses that I can loop through and display in a div. ...

Troubleshooting Issue: Ionic 3 and Angular ngForm not transmitting data

Attempting to create a basic crud app with ionic 3, I am encountering an issue where new data cannot be inserted into the database. The problem seems to lie in the PHP server receiving an empty post array. Below is my Ionic/Angular code: Insert.html < ...

Creating interactive labels in a histogram that update based on the user's input

Currently, I have operational code in place that takes input data and generates a histogram based on set thresholds. When the code is executed, the histogram changes dynamically as the threshold slider is adjusted. However, there seems to be an issue wit ...

typescript Can you explain the significance of square brackets in an interface?

I came across this code snippet in vue at the following GitHub link declare const RefSymbol: unique symbol export declare const RawSymbol: unique symbol export interface Ref<T = any> { value: T [RefSymbol]: true } Can someone explain what Re ...

Tips and tricks for displaying JSON data in Angular 2.4.10

In my Angular project, I am facing an issue while trying to display specific JSON data instead of the entire JSON object. Scenario 1 : import { Component, OnInit } from '@angular/core'; import { HttpService } from 'app/http.service'; ...