The Problem with TypeScript Union Types

I recently started using TypeScript and ran into an issue with a similar scenario. Despite my efforts, I encountered two errors that I can't seem to figure out. If anyone has any insights on how to resolve this, I would greatly appreciate the help!

interface Foo {
    [key: string]: number
};
interface Bar {
    [key: string]: { positive: number, negative: number }
}

// const obj: Foo | Bar = {
//     usa: { positive: 5, negative: 3 },
//     uk: { positive: 4, negative: 1 },
//     fr: { positive: 8, negative: 2 },
// }

const obj: Foo | Bar = {
    usa: 5,
    uk: 3,
    fr: 2,
}

Object.keys(obj).map(key => {
    const val = 'positive' in obj[key] ? obj[key].positive : obj[key];
    alert(val);
})

The errors that are troubling me are:

https://i.sstatic.net/9qC5S.png

https://i.sstatic.net/K4Cor.png

Answer №1

Implementing user defined type guards allows you to inform the compiler that your check is intended to narrow down the type. However, this method is applicable only to variables and not expressions, so you must first assign it to a separate variable.

interface Foo {
    [key: string]: number
};

interface PosNeg {
    positive: number
    negative: number
}

interface Bar {
    [key: string]: PosNeg
}

type FooBar = Foo | Bar

type PossibleValues = FooBar[keyof FooBar]

function isPosNeg(item: PossibleValues): item is PosNeg {
    return typeof item !== "number"
}

const obj: FooBar = {
    usa: 5,
    uk: 3,
    fr: 2,
}

Object.keys(obj).map(key => {
    const item = obj[key]
    const val = isPosNeg(item) ? item.positive : item;
    alert(val)
})

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

Amchart 5: Tracking Cursor Movement on the X Axis

I am a beginner with amCharts5 and I am in need of assistance to retrieve the actual X value of the cursor on my chart (where the X axis represents dates). I have come across helpful examples for amCharts 4, but nothing seems to work for amCharts 5. Is thi ...

Having trouble retrieving the iframe document using JavaScript

I'm currently facing an issue when trying to fetch an image from a website (not specifically Bing, this problem arises with every site). Upon running the code, it seems to be failing at the 'if' statement, indicating that there might not b ...

Steering clear of the generic Function type in React with TypeScript

Can anyone help me find a guideline that prohibits the use of "Function" as a type? myMethod: Function; I have searched but couldn't locate any information on this. Appreciate any suggestions :) ...

Increase the height of an element based on the content of the text within

Today I am facing a challenge: I need the text below to change when I click on one of these icons: https://i.sstatic.net/28xEF.png Luckily, it works with the following code: CSS .games-text { background-color: $color-primary; & p { m ...

A comparison of Vue's import paths: exploring the variations

Exploring the world of Vue has been exciting but I'm a bit puzzled by the syntax used for importing different libraries. Take, for instance, this import statement: import Vue from 'vue'; import axios from 'axios'; Where do these r ...

UI-Router is failing to transition states when $state.go() is called

I am currently troubleshooting a unit test for my user interface router routes, specifically focusing on the issue I encountered with the test not passing successfully. Within my test script, when checking the value of $state.current.name, it returns &apo ...

Expanding the size of a JavaScript array by adding fields

I have extended the JS array prototype by adding a "max" field. However, I am encountering difficulties in displaying this addition when stringifying the array. Despite attempting to modify the toJSON function, my efforts have been unsuccessful. Array.pro ...

A TypeScript class designed to serve as a function type as well

When trying to utilize angular's IHttpService, I am unsure of how to manage the following function. interface IHttpService { <T>(config: IRequestConfig): IHttpPromise<T>; } class MyHttpService implements IHttpService { // The cod ...

When using jQuery with a large selectbox, you may encounter the error message: "Uncaught RangeError: Maximum

My select box works fine in IE and Mozilla, but throws an uncaught rangeError in Chrome when choosing the "Others" option to display a second select box with over 10k options. How can I diagnose and resolve this issue? <!DOCTYPE html> ...

Replace the current picture with a newly uploaded one and keep it consistent

On my webpage, there is an image that I want to be able to replace by clicking on it and selecting a new image from the file uploader without showing the upload button. Once the new image is uploaded, I'd like it to replace the current image, and for ...

What's the best way to test a TSX file importing SCSS using Jest?

Here is my configuration for jest: module.exports = { roots: ['<rootDir>/src'], collectCoverageFrom: [ '<rootDir>/src/**/*.{ts,tsx}' ], coverageDirectory: 'coverage', testEnvironment: 'jsdom&apo ...

The state of the button remains unchanged in jQuery/Rails 3

After immersing myself in the Hartl Rails 3 tutorial for a few days (about 4 to be exact), I encountered an issue while attempting to convert the site from prototype to jQuery in chapter 12. The problem lies in getting the "follow"/"unfollow" button to upd ...

What is the best way to pass a Python string to a JavaScript script?

I attempted to utilize the JSON module for this task, but encountered errors in both my JavaScript script and Firebug. For example, I have a line that looks like this: {"fruit":{"apple":100}} When trying to send this to a JavaScript script called jquery. ...

How can I create a top right profile button similar to Google using AngularJS?

I am looking to implement a floating button in the top right corner of my main screen. When clicked, I want it to open a card below with an arrow pointing towards the button similar to the one on . I am currently using Angular Material and have tried using ...

What are the methods for incorporating reflection into three.js?

While working on a WebGL project using Three.js, I am aiming to incorporate a reflective cube surface that mimics the appearance of a mobile phone display. The surface should be able to reflect light while maintaining a black color scheme. ...

Filtering with multiple attributes in Angular using GroupBy

I have a set of JSON data structured like this: [ { "id": 1, "address": "MG Road", "country": INDIA, "state": AP, "city": VIJ }, { "id": 2, "address": "Miyapur", "country": INDIA, ...

Is it no longer possible to create custom linked Context Menus in Tabulator 5?

After using Tabulator for a few years, we have decided to switch over to Angular v13 and upgrade to the new Tabulator 5.x. In our previous implementation, we had set up a custom ContextMenu in the Table Column Definition like this: contextMenu: this.TableR ...

Dynamic sidebar that adheres to the content and is placed alongside it using JavaScript

I am in need of creating a sticky sidebar that will float beside my content column. The purpose of this sidebar is to contain jump links on the page, similar to what can be seen on this page, but with the navigation buttons positioned directly next to the ...

Adjust the hue of a circle based on whether the user's position falls within its designated range

I am working with a map that displays several circles, each with its own radius. When the page loads, I capture the user's position and show it on the map. Initially, all circles are red. My goal is to determine if the user's current position fal ...

Determining the file path in HTML5

Can anyone help me with retrieving the file path using html5 javascript once a user selects a file? I require the file path for a specific scenario: In this case, the user uploads a file and pauses it (currently only supported by Mozilla browsers), then c ...