What is preventing TypeScript from identifying the type of a parent based on its child?

Take a moment to explore the following example:

type Num = {
    type:  'NUMBER'
    numberValue: number
}

type Str = {
    type: 'STRING',
    stringValue: string
}

type B_Num = {
    a: Num;
    numberData: number;
}

type B_Str = {
    a: Str;
    stringData: string;
}

type A = Num | Str
type B = B_Num | B_Str

function test_Num(num: Num) {}
function test_B_Num(bNum: B_Num) {}

function test_B(b: B) {
    if (b.a.type === 'NUMBER') {
        test_Num(b.a) // Recognizes b.a as Num
        test_B_Num(b)   // Struggles to recognize b as B_Num (typing error occurs)
    }
}

Check out the code in action here.

Have you ever wondered why typescript struggles to identify the specific type of variable b? Even though it has the necessary information (recognizing b as B and b.a as Num).

Answer №1

It appears that TypeScript struggles to automatically determine the correct type for the parent object b based on the type of b.a (in a bottom-up approach). Whether this is a limitation of the language or an expected behavior remains uncertain.

Instead of solely relying on b.a.type === 'NUMBER' for type inference, a more reliable approach could be to check for the presence of numberData in the object b. By adopting this top-down approach, TypeScript is able to accurately infer the types of both b and b.a:

function test_B(b: B) {
    if ('numberData' in b) {
        test_A_NUMBER(b.a) // correctly identifies b.a as A_Number
        test_B_NUMBER(b)   // now correctly identifies b as B_Number
    }
}

Explore and test the modified code in this playground link.

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

Toggle the div if the if statement is true; otherwise, hide the broken

click: function(event, data) { $('#clicked-state') .text('You clicked: '+data.name); if (data.name == "VA") { $('#va').toggle(); } else { $('#va').style.d ...

Could adjusting the 'lib' compiler option to incorporate 'dom' potentially resolve TS error code TS2584?

My preferred development environment is Visual Studio where I write Typescript code. I am facing an issue where I simply want to use the command "document.write" without encountering an error. Unlike my previous PC and VS setup, I am now getting an error ...

Tailwind not properly filling the full width of the screen despite being a fixed element

Can someone assist me in achieving full-width for a fixed element in Tailwind? Check out the modal screenshot here: Modal Screenshot Please disregard the placeholder text as I am still in the testing phase. My React code: import { Dialog, Transition } f ...

What is the best method for calculating the total of a column field within an array in Angular 9.1.9?

I am using Angular 9.1.9 and Html to work with a nested array field in order to calculate the total sum and display it in a row. Within my array list ('adherant'), I am aiming to sum up a specific column's values ({{ Total Amount }}) and pr ...

Setting up a CentOs Linux environment to host and run a node.js server

Just installed node.js on my new VPS server. I have written a basic script called "server.js" and it is currently running on port 8080. The location of the script is in the "var/www/html/" directory. However, whenever I try to access my domain, it only dis ...

What strategies can be implemented to maximize the efficiency of this asynchronous block of code?

var orderItems = userData.shoppingcart; var totalPrice = 0; userData.shoppingcart.forEach(function(itemName, i){ _data.read('menuitems', itemName, function(err, itemData){ if(!err && itemData) { totalPrice += i ...

Using react-i18-next with .json or .js files: a simple guide

Although I am familiar with using i18-next in react components, my current challenge is to import data from either a JS file or JSON file for better code separation. The issue is that I am unable to use the useTranslation hook in those files. I am looking ...

Is it possible to caution users before refreshing the page, while still allowing them to

I have a script that displays a warning message to the user when they attempt to refresh the page. It works perfectly for that purpose. However, my issue is that this same alert pops up when a user clicks on a button or a link within the website itself. I ...

Fundamentals of object property in jQuery and Javascript

Currently working on creating a new property named startPosition and setting the top property to equal the button's current top value in CSS. Below is the jQuery code snippet: var morphObject = { button: $('button.morphButton'), c ...

Changing the background image of the body when hovering over a li element: a step-by-step

For my website, I want to achieve the same effect as seen on the homepage of this site: I am looking to change the background image of my webpage when a specific li element is hovered over. Each li element should trigger a different background image. Add ...

Error retrieving the latest token in Angular before the component has fully loaded

I am seeking relevant advice to address my specific need: In my Angular application, I have implemented a jwt-based authentication system. After obtaining a new token and refresh token, I have set up a setTimeout function to ensure the token is refreshed ...

Add empty objects to an array using a push function following the Vue JS constructor function

During my learning journey with Vue JS, I encountered an issue while attempting to populate an array with objects using a constructor function and the push method. Surprisingly, in Vue JS, the push function inserts a blank object into the array instead of ...

Sending a JavaScript array to an MVC controller in .NET 5.0 via a POST request

Trying to send data from a JavaScript array to an MVC controller. While debugging, I end up in the method public void GetJSArray(List<SelectorModel> selectorModels) However, the selectorModels is currently showing as null. Below is the model being ...

Combining all elements of my application into a single HTML, JS, and CSS file

My AngularJS app has a specific structure that includes different directories for each component: theprojectroot |- src | |- app | | |- index.html | | |- index.js | | |- userhome | | | |- userhome.html | | | ...

Using Angular JS, apply multiple column filters within a table to refine the displayed data

I'm currently working on implementing a filter for multiple columns in a table that is being populated by the ng-repeat directive. <tr ng-repeat="descriptiveField in vm.descriptiveFieldList|filter:{name:vm.searchText}" ng-class-even="'even-bg ...

Is there a way to modify the style within a TS-File?

I've created a service to define different colors and now I want to set separate backgrounds for my columns. However, using the <th> tag doesn't work because both columns immediately get the same color. Here's my code: color-variatio ...

Encountering an error in React when attempting to convert a class component to a function

As I've been converting my class components to functions, I encountered a hook error related to my export default. Although I believe it's a simple issue, I can't seem to find the solution I need. The following code is where the error occur ...

React Native Component Error: Cannot read property '_this' of undefined

I am currently developing a face recognition application using React Native 0.63. I'm running my project using react-native run-android. However, I encountered an issue with Component Exception where it shows 'undefined is not an object (evaluati ...

Sharing context sub files in Next.js can be easily accomplished by following a few simple

These are the pages on my website: /pages /gift /[slug] index.tsx /personalize index.tsx In /gift/[slug]/index.tsx, I have a component called GiftProvider that looks like this: return ( <GiftProvider gift={gift}& ...

Adding options for a select tag from JavaScript can be accomplished by using the DOM manipulation methods

I am working on a form that includes drop-down menus. The options for the select tag need to change dynamically based on the id value. For instance, if the id is 1, the select tag options should be cat and dog. If the id is 2, the options should be apple ...