Ensure that a particular key type is determined by the value of another key within the object (Utilizing Discriminated Unions)

The title of my question may not have been clear about what I am looking for, but what I need is something known as discriminated unions. You can find more information about it here: https://www.typescriptlang.org/docs/handbook/unions-and-intersections.html#discriminating-unio...>

I have a type A with two fields, B and C. Field B has a well-defined set of string literals, and I want field C's type to be dependent on the value of field B.

Here is some code to clarify:

type Field1Values = "a" | "b" | "c";

type TypeForValueA = {
   ...
}

type TypeForValueB = {
   ...
}

type TypeForValueC = {
   ...
}

type RootType = {
    field1: Field1Values,
    field2: <something here that I didn't know exactly what to put>
}


const objA: RootType = {
    field1: "a",
    field2: {
        // Only the values from the type TypeForValueA are allowed
    }

}

const objB: RootType = {
    field1: "b",
    field2: {
        // Only the values from the type TypeForValueB are allowed
    }

}

How can I achieve the desired effect?

Thank you 😃

Edit:

I have already tried following the instructions in the documentation example:

type NetworkState =
  | NetworkLoadingState
  | NetworkFailedState
  | NetworkSuccessState;

However, all the fields from all types are being displayed in the lint results. I only want the fields from the correct type to be shown.

Answer â„–1

Using this playground link, I have provided a new solution that addresses the communication issue between discriminating and discriminated fields in your example.

The main problem with your original approach was the lack of clear mapping between the possible values of the discriminating field and the potential types of the discriminated field. In my revised version, I followed the TypeScript documentation you referenced to create a more structured and informative code snippet.

// The Field1Values type is no longer necessary

type TypeForValueA = {
   fieldForA: string;
}

type TypeForValueB = {
   fieldForB: number;
}

type TypeForValueC = {
   fieldForC: boolean;
}

type RootA = {
    field1: "a";
    field2: TypeForValueA;
}
type RootB = {
    field1: "b";
    field2: TypeForValueB;
}
type RootC = {
    field1: "c";
    field2: TypeForValueC;
}
type RootType = RootA | RootB | RootC;


const objA: RootType = {
    field1: "a",
    // Suggestions for field2 will appear when you press `ctrl+space`
}
const objB: RootType = {
    field1: "b",
    // Suggestions for field2 will appear when you press `ctrl+space`
}
const objC: RootType = {
    field1: "c",
    // Suggestions for field2 will appear when you press `ctrl+space`
}

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

The variable 'key' is declared in the Google Chrome extension V3 local storage, but it appears that its assigned value is never actually accessed

In my TypeScript code, I have defined a function like so: setLocalStorage: async (key: string, value: string): Promise<string> => { return new Promise((resolve, reject) => { chrome.storage.local.set({ key: value }, funct ...

Creating a layout of <video> components in vue.js, complete with the ability to rearrange and resize them through drag and drop functionality

Despite trying numerous libraries and Vue.js plugins, I have yet to find one that meets all of my requirements. I am in need of creating a grid of video HTML elements that are draggable and resizable with a consistent aspect ratio of 16:9. Additionally, I ...

Bring in all subdirectories dynamically and export them

Here is what I currently have: -main.js -routeDir -subfolder1 -index.js -subfolder2 -index.js ... -subfolderN -index.js Depending on a certain condition, the number of subfolders can vary. Is there a way to dynam ...

A critical error has occurred: RangeError - The maximum call stack size has been exceeded while trying to

After attempting to filter a list of titles using Ng2SearchPipeModule, I imported the module in app.module.ts and created a new searchbar component. searchbar.component.ts import { FirebaseService } from './../../firebase.service'; import { Ang ...

Modify the ShortDate formatting from "2020/06/01" to "2020-06-01"

I am looking to modify the shortDate format in my template file. Currently, when I try to change it to use "-", it still displays the date with "/". What I actually want is for the output to be formatted as yyyy-MM-dd. <ngx-datatable-column name="C ...

Route user based on login status using router

I want to set up automatic routing to a login page for users who are not logged in. app.module.ts import { RouterModule, Routes } from '@angular/router'; import { AppComponent } from './app.component'; import { LoginComponent } from &ap ...

Using React-Bootstrap with TypeScript in your project

I'm currently working on creating a navigation bar using react-bootstrap. I've already installed the node-module as follows: "@types/react-bootstrap": "^0.32.11",. However, when I try to use it in my hello.tsx component, I encounter a compile err ...

What is the best way for a function to accommodate various types that adhere to an interface?

How can we create a function that can accept multiple types with a common interface? Let's consider the example: interface A {a: number} type B = {b: string;} & A type C = {c: string;} & A function acceptA(a: A) { return a } acceptA({a ...

Issue with assigning Type (Date|number)[][] to Array<,Array<,string|number>> in Angular with typescript and google charts

Currently, I am utilizing Angular 8 along with the Google Charts module. My latest endeavor involved creating a Google Calendar Chart to complement some existing Google charts within my project. However, upon passing the data in my component.html file, I ...

Angular Build Showing Error with Visual Studio Code 'experimentalDecorators' Configuration

Currently experiencing an issue in VSC where all my typescript classes are triggering intellisense and showing a warning that says: "[ts] Experimental support for is a feature that is subject to change in a future build. Set the 'experimentalDeco ...

Issue with Parcel / React 18 App.js failing to refresh cache

Currently, I am developing a React application for my school project. However, I have encountered an issue where certain components are not rendering in my App.js file. Strangely, when I place these components as child components of App.js, they do render ...

I'm curious about the type I can set for the first parameter of setState in TypeScript. Is there a way to pass a dynamically generated state object to setState?

When trying to pass a newState object to setState and add some additional properties under certain conditions, I encountered a type error: I attempted to define the new State as Pick<ItemListState, keyof ItemListState> but received a type error ...

Angular typed controls allowing for a seamless user experience without the need to

Currently, I am in the process of updating some older forms to include stronger typing in order to address eslint errors. One recurring issue I have encountered is when using the .value operator on abstract controls, it causes an error in my IDE stating "U ...

What is the process for importing a map from an external JSON file?

I have a JSON file with the following configuration data: { "config1": { //this is like a map "a": [ "string1", "string2"], "b": [ "string1", "string2"] } } Previously, before transitioning to TypeScript, the code below worked: import ...

What are the steps to creating an Observable class?

I am working with a class that includes the following properties: export class Model { public id: number; public name: string; } Is there a way to make this class observable, so that changes in its properties can be listened to? I'm hoping fo ...

What is the best way to implement a dispatch function in TypeScript?

Despite my expectations, this code does not pass typechecking. Is there a way to ensure it is well typed in Typescript? const hh = { a: (_: { type: 'a' }) => '', b: (_: { type: 'b' }) => '', } as const; ex ...

In Angular 4, the Bootstrap modal now only opens after a double click instead of opening on the first click

Working on an eCommerce application, there is a cart icon that triggers a modal screen displaying user-selected product data when clicked. However, the issue I'm facing is that upon initial page load, the modal screen opens only after double-clicking; ...

Enhance Typescript with Extension Traits

Picture this scenario: You have a class A with a method that can create an instance of class B. You're unable to make any changes to the code of either A or B, as they are part of an external library. In this situation, if you want to enhance the fun ...

Steps to modify the background color of an IconButton upon clicking in Material UI

After clicking on the IconButton, the background color changes to an oval shape. I now need to modify the background color when it is clicked. CSS The CSS code for the IconButton changes the background color upon hover. I require a similar effect for the ...

Angular2 allows for the firing of all columns in one click using *ngFor

<tr *ngFor = 'let student of students> <td contenteditable="true" class ='phone' #button> {{student.phone}} <i (click)='showbox()' class = ' glyphicon glyphicon-edit'></i> <input *ngIf=&apo ...