When faced with the error message "Typescript property does not exist on union type" it becomes difficult to assess the variable

This question is a continuation of the previous discussion on Typescript property does not exist on union type.

One solution suggested was to utilize the in operator to evaluate objects within the union. Here's an example:

type Obj1 = { message: string }
type Obj2 = { text: string }

const getText = (obj: Obj1 | Obj2): string => {
  if ("message" in obj) {
    return obj.message
  }

  return obj.text
}

However, attempting to evaluate it with a variable causes the same error to occur:

const getText = (obj: Obj1 | Obj2): string => {
   let property = "message"

   if (property in obj) {
      return obj.message
   }

   return obj.text
}

Is there something obvious that I am overlooking?

Answer №1

When the key in a conditional statement is a variable rather than a literal, Typescript does not narrow down the type as expected. Upon hovering over 'obj' in the condition, it shows a type of Obj1 | Obj2.

Although one might expect the compiler to recognize the safety of such conditions, Typescript errs on the side of caution due to its imperfections. It prioritizes reporting potential issues over allowing them to go unnoticed and cause problems in production code.

While this limitation may seem significant, it is rarely encountered in practical scenarios. The presence of the 'message' property is essential in your code for this condition to work, making the use of a variable unnecessary since the type can only be one specific value. Therefore, using a literal string in the test would suffice.


If you frequently encounter this scenario and wish to avoid repeating the same literal, you can create a reusable type guard function like this:

function isObj1(obj: Obj1 | Obj2): obj is Obj1 {
    return 'message' in obj
}

const getText = (obj: Obj1 | Obj2): string => {
   if (isObj1(obj)) {
      return obj.message
   }

   return obj.text
}

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

When utilizing ASP.NET Core Razor pages for file uploads and utilizing AJAX Post to send the file to an IFormFile handler, the request

I have a straightforward task that involves uploading a file and using AJAX to post it to the Index page: <input type="file" id="file-selector" accept=".txt"> Here is the corresponding Javascript: const fileSelector ...

Having trouble setting a value for a textbox in angularjs

Greetings! I am currently working on a web application using AngularJS. My task involves binding data from various API's to a textbox in my project. Below is the snippet of the HTML code where I attempt to achieve this: <input class="with-icon" ty ...

JavaScript equivalent code to C#'s File.ReadLines(filepath) would be reading a file line

Currently in my coding project using C#, I have incorporated the .NET package File.ReadLines(). Is there a way to replicate this functionality in JavaScript? var csvArray = File.ReadLines(filePath).Select(x => x.Split(',')).ToArray(); I am a ...

Run the command "node index.js" to simultaneously start and stop the server

After installing WSL2 and the Ubuntu 22.04 distribution on Windows 11, I set up my environment, installed nvm, Node version 16.17.1, and then ran npm init in my folder. Following that, I installed Express and created an index.js file with a simple structur ...

Massive HTML Table Containing Rows upon Rows

Currently, I have a server that can provide me with a list of objects in json format, and my goal is to showcase them in a table on the client side. Initially, I thought about dynamically modifying the DOM after receiving data from the server. Building th ...

Is it possible to make the v-toolbar-title fixed within a v-navigation-drawer using Vuetify?

Can the <v-toolbar-title> be fixed within a <v-navigation-drawer>? <v-card class="d-inline-block elevation-12"> <v-navigation-drawer hide-overlay permanent stateless height="440" value="true"> <v-toolbar color="whi ...

The ReactDOM.createPortal modal has been successfully mounted onto the DOM, however, there seems to be no visible content

This project utilizes TypeScript and Next.js. Within it, there is a Modal component: interface ModalProps { onCancelModal: () => void; onAcceptModal: () => void; acceptEnabled: boolean; isLoading?: boolean; title: string; } const Modal: Re ...

Guide on accessing the text content within a div element in HTML by triggering a button click

To extract specific text from multiple div tags, I need to trigger an event when clicking a button. <div class="col-lg-3 col-md-6 mb-4"> <div class="pricing-table pricing-secondary"> <div class="price-hea ...

Retrieve Vuejs template by either module or ID

In my .Vue file, I have defined a template along with its subcomponents with the intention of allowing customers to override this template without needing to modify any javascript code. If there exists an element with id="search-result", then that element ...

React Material-UI is notorious for its sluggish performance

I recently started using React Material-ui for the first time. Whenever I run yarn start in my react app, it takes quite a while (approximately 25 seconds) on my setup with an i5 8400 + 16 GB RAM. Initially, I suspected that the delay might be caused by e ...

Menu icon in Next.js/React/Tailwind not triggering close action when clicked again, causing responsiveness issue

Hey there, I'm relatively new to working with Next.js and React. Right now, I'm tackling the challenge of creating a responsive navbar that toggles open and closed when clicking on the hamburger icon (and should also close when clicked outside th ...

Is it possible to activate the nearby dropdown based on the user's selection?

On my html webpage, I have a form that consists of three dropdown menus each with different options: The first dropdown (A) includes choices from 1 to 6, as well as 'not set'. The second dropdown (B) allows selections from 1 to 7, and also has ...

How can I pass props from a page to components in Next.js using getServerSideProps?

Struggling to fetch the coingecko-api for accessing live bitcoin prices. Trying to pass return props of getServerSideProps to my <CalculatorBuy /> component within the <Main /> component. Facing issues when importing async function in calcula ...

How should an iterable be sorted in React?

Let's break down the scenario using pseudo code: {this.props.myIterable.map((iterable) => { return ( <div>iterable.somevalue</div> ) }).sort((a,b) => {return b - a}) To clarify, I am iterating over certain props and displaying ...

Ways to effectively pass arguments to the callback function within the catch function in JavaScript

While working on my code, I suddenly felt the need to pass an extra argument, "msg", to the callback function renderError(). This extra argument should be passed along with the default error argument generated by the catch function itself. I tried doing i ...

Ways to enable automatic scrolling of a page as the content expands (Utilizing collapsible elements)

For a recent project I've been working on, I decided to include 4 collapsible text boxes. However, I encountered an issue where opening content1 would expand and push down content2-4, requiring the user to manually scroll to view the remaining collaps ...

Attempting to create an animated carousel slider

I've been working on creating a carousel animation that displays 3 images, slides them to the left, and brings in new ones. I'm feeling a bit stuck and could use some assistance. Check out my work so far on this fiddle link: http://jsfiddle.net/ ...

Understanding the scope of variables in a JavaScript callback function

I am attempting to send an object variable to a callback function const sql = require('mssql'); const asset_update = function (connection, addr) { this.connection = connection; this.addr = addr; this.addr_long = parseInt(addr, 16); } ...

Assigning a new classification to the primary object in the evolving array of objects

I'm working with an element that loops through all the objects using v-for and has a CSS class named top-class{}... I need to dynamically add the top-class to the first object (object[0]) and update it based on changes, removing the old top-class in t ...

Dealing with JSON Stringify and parsing errors in AJAX

I've been troubleshooting this issue for hours, trying various suggestions found online, but I'm still encountering a problem. Whenever I encode function parameters using JSON.stringify and send them to my PHP handler through AJAX, I receive a pa ...