Issues with Tagged Union Types in Visual Studio Code

Currently, I am working on implementing a tagged union type pattern for my action creators within a redux application. The TypeScript compiles without any issues, however, my code editor, Visual Studio Code 1.26.1, is flagging an error.

[ts] Type 'boolean | { open: boolean; }' is not assignable to type 'boolean'. Type '{ open: boolean; }' is not assignable to type 'boolean'.

The version of TypeScript displayed in the bottom right corner is TypeScript 3.0, which aligns with the version being used in my project. According to my understanding of TypeScript, it should be able to infer the correct type based on the value provided. While this functionality appears to be working from a TypeScript perspective, the error in VS Code persists.

reducer

import { Action } from '../actions';

interface State {
  open: boolean;
};

const defaultState : State = {
  open: false,
};

export default (state = defaultState, { type, payload } : Action) : State => {
  switch(type) {
    case 'PASSWORD/OPEN':
      return { ...state, open: payload } // ERROR here on open property
  }
}

actions/index.ts

import { PasswordAction, openPassword, closePassword } from './password';
export type Action = PasswordAction;
export default {
  openPassword,
  closePassword,
};

actions/password.ts

interface OpenAction {
  type: 'PASSWORD/OPEN';
  payload: boolean;
}

interface CloseAction {
  type: 'PASSWORD/CLOSE';
  payload: { open: boolean; };
}

export type PasswordAction = OpenAction | CloseAction;

export const openPassword = () : OpenAction => ({
  type: 'PASSWORD/OPEN',
  payload: true,
});

export const closePassword = () : CloseAction => ({
  type: 'PASSWORD/CLOSE',
  payload: {open: false},
});

Disclaimer

This issue might not be directly related to programming and could potentially be considered off-topic. Initially, I planned to raise the question on their GitHub page, but upon reviewing the issue checklist, it suggested asking questions here. Since I am uncertain if this is a bug, I wanted to seek clarification here first.

Answer №1

To enable the type guards connected with discriminated unions to function properly, it is important not to destructure the union. If you do this, Typescript will lose track of the relationship between the destructured variables. The following code example demonstrates how to make it work:

export default (state = defaultState, a : Action) : State => {
  switch(a.type) {
    case 'PASSWORD/OPEN':
      return { ...state, open: a.payload }
  }
}

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

Enhancing Angular Material: requiring more user engagement for rendering to occur

Encountering an unusual issue with Angular Material: certain components require an additional event, like a click or mouse movement on the targeted div, to trigger the actual rendering process. For instance, when loading new rows in mat-table, some empty ...

Calculate the sum of multiple user-selected items in an array to display the total (using Angular)

Within my project, specifically in summary.component.ts, I have two arrays that are interdependent: state: State[] city: City[] selection: number[] = number The state.ts class looks like this: id: number name: string And the city.ts class is defined as f ...

Prevent Click Event on Angular Mat-Button

One of the challenges I'm facing involves a column with buttons within a mat-table. These buttons need to be enabled or disabled based on a value, which is working as intended. However, a new issue arises when a user clicks on a disabled button, resul ...

Tips for efficiently inserting large amounts of data using a select subquery

I'm currently using Sequelize in my project and encountering difficulties in converting a simple query into Sequelize syntax. Furthermore, I am also exploring ways to efficiently perform bulk inserts for this particular query. The query in question i ...

Storing Angular header values in local storage

saveStudentDetails(values) { const studentData = {}; studentData['id'] = values.id; studentData['password'] = values.password; this.crudService.loginstudent(studentData).subscribe(result => { // Here should be the val ...

What is the best way to transform a JS const into TSX within a Next.js application?

Exploring the code in a captivating project on GitHub has been quite an adventure. The project, located at https://github.com/MaximeHeckel/linear-vaporwave-react-three-fiber, showcases a 3D next.js application that enables 3D rendering and animation of mes ...

Updating from version 1.8.10 to 2.9.2 and encountering a build error in version 4.6.4

I currently have an angular application that is using typescript version 1.8.10 and everything is running smoothly. However, I am interested in upgrading the typescript version to 2.9.2. After making this change in my package.json file and running npm inst ...

Is there a way to position the label to the left side of the gauge?

Is there a way to position the zero number outside the gauge? I'm having trouble figuring out how to do it because the x & y options won't work since the plotLine's position keeps changing. The zero needs to move along with the plotLine and ...

What steps do I need to take in order to activate scrolling in a Modal using Material-UI

Can a Modal be designed to work like a Dialog with the scroll set to 'paper'? I have a large amount of text to show in the Modal, but it exceeds the browser window's size without any scrolling option. ...

Stop the MatSort feature from activating when the space key is pressed in Angular Material

I am currently using angular material tables and have implemented filters for each column. The filter inputs are located in the row header of each column, which is working fine. However, I am facing an issue where whenever I type and press the space key, ...

Modifying the response header in a node.js middleware: A step-by-step guide

I've been researching this question extensively on Google, but unfortunately, none of the solutions seem to work for me. The issue I'm facing is related to adding a specific property to the response header called "isAuth," which needs to be set ...

Angular button press

Recently, I started learning Angular and came across a challenge that I need help with. Here is the scenario: <button *ngIf="entryControlEnabled && !gateOpen" class="bottomButton red" (click)="openGate()">Open</button> <button *ngIf ...

Steps to retrieve a date from a form control

html <form [formGroup]="searchForm" (ngSubmit)="search()"> <div class="row"> <div class="col"> <input type="date" class="form-control" formControlName="startD ...

Error caused by properties of a variable derived from an interface in the compiler

I'm confused as to why the compiler is saying that the properties "name" and "surname" don't exist on type "ITest1" within function test1. It's a bit unclear to me: interface ITest1{ name: string; surname: string; age: number; } ...

There is a chance that the object could be 'undefined' when attempting to add data to it

I created an object and a property called formTemplateValues. I am certain that this property exists, but I am getting an error message saying: "Object is possibly 'undefined'". It should not be undefined because I specifically created it. Why am ...

When a TypeScript merged declaration composition is used with an extended target class, it fails to work properly

I have a TypeScript problem where I need to combine a class that has been extended with a few others. While searching for solutions, I came across an article outlining a pattern that I thought could be helpful: https://www.typescriptlang.org/docs/handbook ...

The class 'GeoJSON' is mistakenly extending the base class 'FeatureGroup'

Encountering an error message in one of my projects: test/node_modules/@types/leaflet/index.d.ts(856,11): error TS2415: Class 'GeoJSON' incorrectly extends base class 'FeatureGroup'. Types of property 'setStyle' are incompa ...

ESLint version 8.0.0 encountered an error while attempting to fetch the '@typescript-eslint' plugin

Hey there, I'm in need of some assistance. I encountered an error while trying to build a project. Uh-oh! Something didn't go as planned! :( ESLint: 8.0.0 TypeError: Failed to load plugin '@typescript-eslint' specified in ' ...

Limiting the height of a grid item in MaterialUI to be no taller than another grid item

How can I create a grid with 4 items where the fourth item is taller than the others, determining the overall height of the grid? Is it possible to limit the height of the fourth item (h4) to match the height of the first item (h1) so that h4 = Grid height ...

Combine form data from a reactive form into a string using interpolation

Currently, I am working with an object that has a string property embedded within it. The string in this property contains interpolation elements. For my user interface, I have implemented a reactive form with an input field. My goal is to display the ent ...