TS2339: The specified property 'X' cannot be found on type 'Y' due to being a non-indexable type in a union case

Contrast with a similar query

In the previous inquiry about error TS2339: Property 'x' does not exist on type 'Y', the focus was on the concept of indexable type. This current scenario, however, appears to require different approaches for resolution.

Issue at Hand

interface INumberPropertySpecification__CommonParameters {
  readonly type: PROPERTIES_TYPES.NUMBER; // enum
  readonly numberType: NUMBER_TYPES; // enum
}

export type NumberPropertySpecification =
      INumberPropertySpecification__Required |
      INumberPropertySpecification__HasDefault |
      INumberPropertySpecification__Optional;

The code snippet above defines the NumberPropertySpecification as a union of three possible cases:

  1. When the property is mandatory, users must explicitly specify required: true.
interface INumberPropertySpecification__Required extends INumberPropertySpecification__CommonParameters {
    readonly required: true;
    readonly invalidValueSubstitution?: number;
}

// Example:

const requiredNumberPropertySpecification: INumberPropertySpecification__Required = {
  type: PROPERTIES_TYPES.NUMBER,
  numberType: NUMBER_TYPES.ANY_REAL_NUMBER,
  required: true 
}
  1. If the property has a default value and is not required, specifying required: false is unnecessary.
interface INumberPropertySpecification__HasDefault extends INumberPropertySpecification__CommonParameters {
    readonly defaultValue: number;
}

// Example
const requiredNumberPropertySpecification: INumberPropertySpecification__HasDefault = {
  type: PROPERTIES_TYPES.NUMBER,
  numberType: NUMBER_TYPES.ANY_REAL_NUMBER,
  default: 1
}
  1. For optional properties, users are required to explicitly state required: false:
interface INumberPropertySpecification__Optional extends INumberPropertySpecification__CommonParameters {
    readonly required: false;
}

// Example:

const requiredNumberPropertySpecification: INumberPropertySpecification__Optional = {
  type: PROPERTIES_TYPES.NUMBER,
  numberType: NUMBER_TYPES.ANY_REAL_NUMBER,
  required: false 
}

Error Troubleshooting

It is noted that checking

targetPropertySpecification.required === true
may lead to unnecessary complications in TypeScript's type check algorithm. A simpler approach would be preferable to avoid potential errors caused by undefined values.

Similarly, handling defaultValue (the isUndefined) warrants attention:

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

A comparable issue arises when dealing with defaultValue, emphasizing the importance of proper error detection:

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

Answer №1

Your implementation bears resemblance to a concept known as discriminated union, although you utilize the 'required' field for this purpose.

In JavaScript (and TypeScript), there is a distinction between an existing property with an 'undefined' value and a non-existent property. To ensure the functionality of your code, it is recommended to include optional properties like 'required' and 'defaultValue' in all interfaces.

interface INumberPropertySpecification__Required extends INumberPropertySpecification__CommonParameters {
  readonly required: true;
  readonly invalidValueSubstitution?: number;
  readonly defaultValue?: undefined;
}

The type of 'defaultValue' is explicitly set as 'undefined' and designated as optional.

Similar modifications need to be made to the other two interfaces as well.

interface INumberPropertySpecification__HasDefault extends INumberPropertySpecification__CommonParameters {
  readonly defaultValue: number;
  readonly required?: undefined;
}

interface INumberPropertySpecification__Optional extends INumberPropertySpecification__CommonParameters {
  readonly required: false;
  readonly defaultValue?: undefined;
}

Following these adjustments, you can proceed with code execution:

const targetPropertySepcification: NumberPropertySpecification = {
  required: true,
  type: PROPERTIES_TYPES.NUMBER,
  numberType: NUMBER_TYPES.T1
}

No value needs to be provided for 'defaultValue'. It defaults to 'undefined'.

The subsequent code snippet will also function correctly:

function f1(targetPropertySepcification: NumberPropertySpecification) {
  if (targetPropertySepcification.required === true) {
    // targetPropertySepcification falls under the type INumberPropertySpecification__Required
    const n: number | undefined = targetPropertySepcification.invalidValueSubstitution;
  } else if (targetPropertySepcification.required === false) {
    // targetPropertySepcification belongs to the type INumberPropertySpecification__Optional
  } else if (targetPropertySepcification.required === undefined) {
    // targetPropertySepcification corresponds to the type INumberPropertySpecification__HasDefault
    const n: number = targetPropertySepcification.defaultValue;
  }

  if (targetPropertySepcification.defaultValue === undefined) {
    // Here targetPropertySepcification represents the type INumberPropertySpecification__Required | INumberPropertySpecification__Optional 
    //  where required property is either true or false, essentially boolean
    const rt: boolean = targetPropertySepcification.required
  }
}

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

Combining switch statements from various classes

Is there a way to merge switch statements from two different classes, both with the same function name, into one without manually overriding the function or copying and pasting code? Class A: protected casesHandler(): void { switch (case){ ...

Encountering the following issue: "ERROR TypeError: Argument is required in IE 11"

The code below is functioning properly in all internet browsers except for IE11. When running the code in IE, an error is thrown stating "ERROR TypeError: Argument not optional." The project being developed is using Angular 10. private togglePageClass(mod ...

What is the best way to clear a form in a Next.js 13.4 component following a server action?

Currently, I am working on a component using next.js 13.4, typescript, and resend functionality. My code is functioning properly without clearing data from inputs, as it uses the "action" attribute which is commented out. However, I started incorporating ...

Customizing event typings for OpenTok in Typescript

Currently, I am working on integrating chat functionality using the 'signal' events with the OpenTok API. Here is my event listener that successfully receives the signal: // Listen for signal CHAT_MESSAGE sess.on('signal:CHAT_MESSAGE', ...

Passing an array of items as a property to a child component in React with Typescript is not possible

In my project, I have multiple classes designed with create-react-app. I am trying to send an array of objects to child components as illustrated below. Items.tsx import * as React from 'react'; import ItemTable from './ItemTable'; imp ...

When I utilize nuxt alongside TypeScript in conjunction with koa and execute the "dev" command, the terminal alerts me of compilation issues within Vue files that incorporate TypeScript syntax

nuxt: 2.6.2 node: 16.5.0 koa: 2.7.0 Here is the content of my package.json file : { ... "scripts": { "dev": "cross-env NODE_ENV=development nodemon server/index.ts --watch server --exec babel-node --presets @babel/ ...

What methods can I use to optimize the process of updating a vast list of items with await?

I have a large list of items to update and I need to set prices. for... currentItem.attributes.menuItemPrice10 = currentItem.attributes.menuItemPrice1 + .28; await this.menuItemsService.save(currentItem); While this process works fine, I have noticed tha ...

How can I display and link a base64 string to an Image as a source in Nativescript?

I'm having trouble displaying and binding a base64 image as an ImageSource in my View. The image doesn't show up at all, and I couldn't find any helpful information about it in the documentation. Am I missing something? The imageSource prop ...

The Angular Node server is responding with the error message "You have entered 'undefined' instead of a stream."

Using angular 9 + universal has been smooth sailing until I encountered an issue after building the app with npm run build:ssr and attempting to run it using node: node dist/app/server/main.js. The error message that popped up in the terminal was: Node ...

Utilizing Angular to convert a string array into an array of enum values through an HTTP GET request

I have a list of different user roles defined in my typescript code: enum UserRole { CONSULTANT, MANAGER, ... } There is a REST endpoint /users/id/roles that returns an array of strings representing the roles of a specific user: [ "CONSU ...

Issue Error: NG0201: NgControl provider not found within NodeInjector

My creativity has hit a roadblock and I'm looking for some help. I decided to use the Reactive Forms Module in Angular, so I imported it into my app.module.ts as shown below: import { ReactiveFormsModule } from '@angular/forms'; @NgModule({ ...

SVG polyline animation that persists seamlessly

In my TypeScript code, I have implemented a function that creates a polyline based on 4 different points (x1y1, xCy1, xCy1, x2y2), where Xc represents the half distance between x1 and x2 on a plane. This polyline does not form a circular shape. private cre ...

Understanding how to integrate compiled Typescript AMD modules into the Magento2 platform

I have been working on integrating Typescript support into Magento 2 to modernize it. Everything seems to compile correctly, but I am facing an issue with loading it. My require-config.js file looks like this: var config = { deps: [ "web/js/a ...

Transform a struggling Observable into a successful one

When working with an HTTP service that returns an observable, I encountered an error during the subscribe process for a specific use case that I would like to address within the successful path. My scenario looks like this: In my service class: class My ...

Error: the attempt to execute the mongoose connection function has failed due to it not being recognized as a valid function

Hey there, I'm encountering the error TypeError: mongoose__WEBPACK_IMPORTED_MODULE_15___default.a.connect is not a function import mongoose from "mongoose"; const dbURI = 'myurlstuffhere'; mongoose.connect(dbURI , {useNewUrlParser: ...

Ways to implement a filter pipe on a property within an array of objects with an unspecified value

Currently, I'm tackling a project in Angular 8 and my data consists of an array of objects with various values: let studentArray = [ { Name: 'Anu', Mark: 50, IsPassed: true }, { Name: 'Raj', Mark: 20, IsPassed: false }, { Na ...

Having trouble with the Angular 17 Router functionality when running on a node server

I find myself facing an unusual situation. I am currently developing a basic app that needs to navigate from the landing-page (directory '') to a form component (directory '/form') using Angular 17 and node.js with express.js. I have no ...

Issue with Angular 2 pipe causing unexpected undefined result

Here is a JSON format that I am working with: [{ "id": 9156, "slug": "chicken-seekh-wrap", "type": "dish", "title": "Chicken Seekh Wrap", "cuisine_type": [2140] }, { "id": 9150, "slug": "green-salad", "type": "dish", "title": "Green Sala ...

Issue with Cypress: The 'each' property is missing on type 'TestFunction'

We recently implemented cypress 9.3.1 into our project for end-to-end testing. However, we are encountering an issue where our existing jest tests are not compiling in the CI pipeline. All parameterized tests are showing the following error: Property &apo ...

Specify specific data types for a dynamically generated class method

Imagine having a scenario with the following class: class Example { method1 = this.generateDynamicFunction((param: string) => { return "string" + param; }); method2 = this.generateDynamicFunction((param: number) => { return 1 + param; ...