Use a ternary statement in TypeScript to determine the type to assign

I am facing a scenario where I have the following structure:

selection: (InterfaceX | InterfaceY)[]

interface InterfaceX {
  switch: boolean
  propertyOne: number
}

interface InterfaceY {
  switch: boolean
  propertyTwo: number
}

The possible selections are:

{switch: true, propertyOne: 1} or {switch: false, propertyTwo: 2}

This setup leads to type errors when trying to handle it in a ternary operation:

selection.switch ? selection.propertyOne : selection.propertyTwo

TS2339: Property 'propertyOne' does not exist on type 'InterfaceY'.

And also results in:

TS2339: Property 'propertyTwo' does not exist on type 'InterfaceX'.

My question is, is there a way to specify which interface should be used on each side of the ternary operator? For example, if the switch is true use InterfaceX, otherwise use InterfaceY. I want to achieve this without modifying the existing interfaces. Thank you!

Here's a new example to illustrate the issue:

import React from "react";

export interface Props {
  items: (InterfaceX | InterfaceY)[];
}

interface InterfaceX {
  toggle: true;
  sharedProp: string;
  propertyX: string;
}

interface InterfaceY {
  toggle: false;
  sharedProp: string;
  propertyY: string;
}

export const Picks = (props: Props) => {
  const { items } = props;
  return items.map(item =>
    item.toggle ? (
      <div>
        {item.sharedProp} {item.propertyX} // Unresolved variable propertyX
      </div>
    ) : (
      <div>
        {item.sharedProp} {item.propertyY} // Unresolved variable propertyY
      </div>
    )
  );
};

Answer №1

After reviewing your example, it is essential for the switch property to have an exact value (not boolean) in order for TypeScript to effectively distinguish between the two types. Otherwise, if both values can be false and true, there will be ambiguity regarding the type.

For instance:

interface InterfaceX {
  switch: true;
  propertyOne: number;
}

interface InterfaceY {
  switch: false;
  propertyTwo: number;
}

const fn1 = (selection: InterfaceX | InterfaceY) => {
  selection.switch ? selection.propertyOne : selection.propertyTwo
}

const fn2 = (selection: InterfaceX | InterfaceY) => {
  switch (selection.switch) {
    case true:
      return selection.propertyOne;
    case false:
      return selection.propertyTwo
  }
}

TypeScript 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

Create a package themed with Material UI for export

I am attempting to create a new npm package that exports all @material-ui/core components with my own theme. I am currently using TypeScript and Rollup, but encountering difficulties. Here is the code I have: index.ts export { Button } from '@materia ...

Link the ngModel input to an object within an ngFor iteration

Looking to create a dynamic form using an array that includes FieldLabel and DataModel references. I want to use the DataModel as an object reference, so when the user updates an input field, the referenced model is updated. I have searched extensively bu ...

Error encountered when attempting to locate the file declaration for module 'jwt-decode'

Currently, I am utilizing the Visual Studio 2017 template for my Angular project and encountering an issue when attempting to import the 'jwt-decode' module after adding it to package.json. The error (mentioned in the title of my post) arises aft ...

What is the best way to retrieve all the keys from an array?

I am looking to retrieve the address, latitude, and longitude data dynamically: let Orders= [{ pedido: this.listAddress[0].address, lat: this.listAddress[0].lat, lng: this.listAddress[0].lng }] The above code only fetches the first item from the lis ...

Incorporating Bootstrap Modal into a TypeScript-based minimalist web application

I want to incorporate the Bootstrap Modal component into my TypeScript application. Therefore, I added the necessary types: npm i @types/bootstrap After that, in my TypeScript code: import { Modal } from "bootstrap"; const myModal = new Modal(&a ...

What was the process for implementing the lexer and parser?

My journey into the depths of programming languages led me to explore how TypeScript is implemented, prompting me to venture into its Github repository. Within the language's source code under /src/compiler, I stumbled upon intriguing files like scan ...

Activate expansive pop-up windows with primeng's dynamic dialog feature

In my Angular web application, I am using the PrimeNg modal extension to display modal popups. I have successfully passed a component to the modal service with the following code: const ref = this.dialogService.open(LogsComponent, { data: { ...

Dealing with Observables can lead to the variable returning as undefined

Could someone please clarify why the variable this.userDataObserver is undefined, causing the .next() function to fail? I'm quite puzzled by this. I am in need of pushing some data into a service variable that can be accessed from other components (I ...

Diverse behaviors exhibited by an array of promises

I've developed a function that generates an array of promises: async addDefect(payload) { this.newDefect.setNote(payload.note); this.newDefect.setPriority(payload.priority); const name = await this.storage.get(StorageKeys.NAME); ...

Ways to eliminate blank spaces in a document

How do I remove whitespaces from a text string in my Angular application? For example: {{ someobject.name }} The value of someobject.name is "name abc" I want to achieve the result as "nameabc" (by removing all whitespaces). I have already created a ...

Changing the Angular form based on the value selected from the drop-down menu

I am currently working on a Reactive form in Angular 7 that includes 2 dropdowns (select) which are supposed to function as cascading dropdowns. However, I am facing an issue where the cascading dropdowns are not working as intended. Whenever I select an o ...

Arranging elements into variables in ReactJS

Can multiple different parts of a component be composed into a variable? documentation const App = () => { let element; element = <View> <Text>text</Text> </View>; // --> OK element = element + <View> ...

Guide on utilizing interface within a class for functional de-structuring in TypeScript

In my current project, I have a Class that contains a method which I would like to utilize in a de-structured manner, primarily due to the presence of multiple optional arguments. To maintain strict typing, I have created an Interface to define these argum ...

TS - deduce the specific type of a key value without receiving a union type

Welcome to the coding playground: Click here to start coding Let's talk about a scenario where a function is expected to return some value based on an input argument. The challenge arises when there are keys with the same name but different types re ...

Destructuring an array of strings for use as parameters

Hey guys, I'm working with an array of keys here Example 1: let keyArray = ['x', 'y', 'z'] I'm trying to find a way to use these keys as parameters without repeating them multiple times. Do you have any suggestions ...

Troubleshooting TS Errors in Vue 3 and Vite with Typescript Integration

Currently experimenting with Vue 3, Vite, and TypeScript to build a Vue project. The configuration process has proven to be quite challenging. Despite consulting various documentation sources, I have not been successful in achieving my desired outcome. My ...

Yes, indeed - Entering the schema of a retrieved field from an Object schema

After deciding to upgrade from Yup version 0.29 to 1.2, I encountered some challenges with its types. Seeking assistance in finding the best solution for typing yup schemas. In version 0.29, the universal type Schema fit everywhere, but now it no longer d ...

Ways to create a generic implementation of "typeof obj[keyof typeof obj]"

Looking to define a new type containing all values from an object, with the following structure: const MyBar = { Benchpress : 1, Squats : 2 } as const; An attempt was made to create a type but encountered difficulties: type EnumLike<T extends {}> ...

How can you arrange a List of Objects by property in Angular?

When working with Java, the Comparable interface can be utilized to sort Objects by specific fields. As shown in the example below, we are sorting Fruit objects based on their quantity. public class Fruit implements Comparable<Fruit> { private ...

Insert the object into a designated location within a multi-dimensional array

I've integrated a tree view into my Angular project and I'm looking to add an object to a specific position within an array. array const TREE_DATA: TreeNode[] = [{"name":"Demo","id":"demo_1","children ...