What could be causing the issue with type inference when working with union types that include the 'any' type?

Whenever I utilize a union type where one of the types is any, the TypeScript editor doesn't seem to correctly determine the type. Here is an example:

interface ITest {
    name: string;
    age: number;
}

interface ITest2 {
    last: string;
    dob: number;
}

function isGood(input: any) : input is ITest{
    return 'name' in input && 'age' in input;
}

function doIt(){
    var data : ITest2 | ITest  = {
        last: 'Test', dob: 123
    }

    var data2 : any | ITest = {
        name: 'else', age: 45
    }

    if(isGood(data)){
        alert(`name:${data.name}, age:${data.age}`); // data shows ITest
    }

    if(isGood(data2)){
        alert(`name:${data2.name}, age:${data2.age}`); // data2 shows any
    }
}

doIt();

The code does work properly, but the developer experience at design time isn't as expected (both in VS Code - 1.4.0 and in the TypeScript playground - 1.8).

As anticipated, the following line infers that data is of type ITest based on the type guard.

alert(`name:${data.name}, age:${data.age}`); // data shows ITest

However, with the second part involving data2, it fails to infer the correct type and defaults to any:

alert(`name:${data2.name}, age:${data2.age}`); // data2 shows any

In this scenario, it's expected for intellisense to recognize that data2 should be of type

ITest</code, similar to how it did for <code>data
.

I have attempted swapping the placement of the two types in the union declaration, however, it didn't alter the outcome.

Is there something I'm overlooking?

Practical Application

The actual situation I'm dealing with involves receiving a response from an HTTP call. Initially, it has to be of type any since the HTTP clients are unaware of our data types.

Nevertheless, I aim to create a user-defined type guard that validates the desired properties from that json object, then extracts only the necessary data and returns it.

Answer №1

Expanding the type to accommodate the type guard. The use of any widens the scope compared to ITest, making it default to any. However, when a more specific type is defined, such as ITest, it correctly identifies it:

var data2 : {} | ITest = {
    name: 'else', age: 45
}

This behavior occurs because any encompasses all types, rendering the combination of any | ITest redundant as it is essentially equivalent to any.

Edit: It's worth noting that removing the type declaration altogether also works, even if implicit any mode is disabled. For example:

var data2 = {
    name: 'else', age: 45
}

Second edit: Revised the explanation for clarity based on feedback from comments suggesting some confusion.

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

Filtering Typescript by property values of an interface that match its own values

Looking to extract specific types based on a given label Take a look at the code snippets below: interface TypeWithLabel { label: string; list: string; } interface A extends TypeWithLabel{ label: 'a'; list: '1' | &apo ...

Typescript is facing an issue locating the declaration file

I'm encountering an issue with TypeScript not recognizing my declaration file, even though it exists. Can anyone provide insight into why this might be happening? Here is the structure of my project: scr - main.ts - dec.d.ts str-utils - index. ...

Change the color of certain rows in the table

I'm currently working on a project using Angular4 and ngx-datatable, so my .html file looks like this: <ngx-datatable> <ngx-datatable-column> <ng-template> ... {{row.value}} My goal is to check the value of eac ...

Error: Unable to generate MD5 hash for the file located at 'C:....gradle-bintray-plugin-1.7.3.jar' in Ionic framework

When attempting to use the command ionic cordova run android, an error occurred that prevented the successful execution: The process failed due to inability to create an MD5 hash for a specific file in the specified directory. This issue arose despite suc ...

What tips should be followed when setting up the stencil repository?

Is there a preferred method for defining fields when setting up a Stencil store? The documentation provided online primarily showcases examples with numbers, but what about situations involving objects, strings, or booleans? Should we use the 'as&apo ...

Creating a cutting-edge object using Angular 4 class - The power of dynamism

Attempting to create a dynamic object within a function, but encountering recognition issues. function1(object: object) { return new object(); } The function is invoked as follows: function1(Test) 'Test' represents a basic Class implementatio ...

The type argument '(id: any, title: any, body: any, image: any) => Element' does not match the parameter type

Hello there, I am a beginner in React-Native and I'm facing an issue while trying to map data into View. Despite going through the documentation and other resources, I haven't been able to figure out what mistake I might be making. Can anyone hel ...

Guide on incorporating a bespoke cordova plugin into your Ionic 4 project

After successfully completing all the necessary steps to create a new Cordova plugin as outlined in the link below: Start android activity from cordova plugin I executed the command cordova plugin ls which returned the following result: com.example.sam ...

Methods for setting a global instance within a local function

Hello, I'm fairly new to using TypeScript and Angular2. Let me quickly explain what I'm trying to accomplish with my method. I have some hard-coded XML data that I need to parse into JSON format. Once parsed, each JSON object needs to be assigned ...

The file transfer functionality in object FileTransfert is malfunctioning on certain Android devices when attempting to upload

A mobile application was created to facilitate the sharing of items. Users are required to provide information about the item they are sending, along with the option to add a picture of the object. To achieve this functionality, plugins such as cordova f ...

What is the best way to implement event handling for multi-level components/templates in Angular 5?

Currently, I am immersed in a project using Angular 5. One of the templates, called Template A, is filled with various HTML elements. I am incorporating Template A into another template, Template B, which offers additional functionalities on top of Templat ...

Replace the default Material UI 5.0 typography theme with custom fonts on a global scale

My current challenge involves incorporating two personal fonts into the Material UI 5.0. My goal is to apply these fonts globally by overriding the theme settings. However, I have encountered issues with loading the fonts properly and modifying the typogra ...

Troubleshooting a child process created by electron in Visual Studio Code

I am currently in the process of developing an electron application using typescript and webpack. I have encountered a specific debugging issue with vscode that I would like some assistance with: Context: The main process initiates a child process by call ...

Breaking apart a combination of unions into a collective group of tuples within TypeScript

Looking for a solution similar to TypeScript extract union type from tuple, this question delves into how to split ['a' | 'b', number] into ['a', number] | ['b', number] rather than focusing on why they are not direc ...

Securing Angular 2 routes with Firebase authentication using AuthGuard

Attempting to create an AuthGuard for Angular 2 routes with Firebase Auth integration. This is the implementation of the AuthGuard Service: import { Injectable } from '@angular/core'; import { CanActivate, Router, Activated ...

Ensure to verify within the ngOnInit function whether the checkbox has been selected

Hi everyone, I'm currently facing a situation where I have a list of checkboxes on one screen. When I select some checkboxes, they move to another screen and remain selected there. However, the issue is that when I try to use a button on the second sc ...

Guide on utilizing async/await in .ts files (Encountering error message: "async functions can only be used when targeting ECMAScript 6 or above")

Initially, my project consisted of only app.js using ExpressJS as the main file with numerous lines of code. My development manager instructed me to refactor the code and move some functions into a separate .ts file (transition from JavaScript to TypeScrip ...

What steps do I need to take to implement Dispatch in a React Native project?

Context App.tsx import React, { createContext, useContext, useReducer, useEffect, ReactNode, Dispatch, } from "react"; import AsyncStorage from "@react-native-async-storage/async-storage"; import { StateType, ActionType } f ...

In Vue3, when using the `script setup` with the `withDefaults` option for a nested object, its attributes are marked as required. How can this issue

I have defined a props object with certain attributes: interface Props { formList: BaseSearchFormListItemType[], inline?: boolean searchBtn?: { show?: boolean text?: string type?: string size?: string } } const props = withDefaults( ...

Angular2 input field with one-way databinding

Looking for a simple solution - I have a component with a string that I want to display in an input field. I attempted the following approach, but it didn't work as expected: import {Component} from "@angular/core"; @Component({ select ...