Writing for: Either attribute "a" is defined or attributes "b" and "c" are both defined

How can TypeScript understand whether this.a will be set or if this.b and this.c will be set?

In the given code, it is ensured that there will never be a situation where all items are set or none are set due to how the constructor is structured.

export class MyClass {

  readonly a?: SomeClass
  readonly b?: string
  readonly c?: string

  constructor(a: SomeClass)
  constructor(b: string, c: string)
  constructor(...args: ([SomeClass] | [string, string])) {
    if(args.length === 1) {
      this.a = args[0]
    } else {
      this.b = args[0]
      this.c = args[1]
    }
  }

  echo() {
    if (this.a instanceof SomeClass) {
    } else {
       someFunction(this.b, this.c)
    }
  }

}

someFunction is showing an error:

Argument of type 'string | undefined' is not assignable to parameter of type 'string'.

I am aware of using

else if(typeof this.b === 'string' && typeof this.c === 'string')
, but I'm looking for a more concise approach. Is there another way to solve this?

Example

Answer №1

Either the property "a" is defined or both properties "b" and "c" are defined

The main idea here revolves around the concept of "or". Utilize a TypeScript union type to achieve this, such as {a} | {b,c}. Below is a comprehensive example:

class SomeClass { };

export class MyClass {

    readonly values: { a: SomeClass } | { b: string, c: string }

    constructor(a: SomeClass)
    constructor(b: string, c: string)
    constructor(...args: ([SomeClass] | [string, string])) {
        if (args.length === 1) {
            this.values = { a: args[0] };
        } else {
            this.values = { b: args[0], c: args[1] };
        }
    }

    echo() {
        if ('a' in this.values) {
            const { a } = this.values;
        } else {
            const { b, c } = this.values;
        }
    }
}

Answer №2

//if this.a is not defined, then execute someFunction with this.b and this.c
if (!this.a) {
    someFunction(this.b!, this.c!)    
}

// alternatively, only call someFunction if both this.b and this.c are assigned strings
if(this.b && this.c){
    someFunction(this.b, this.c)
}

Link to Interactive 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

Is it possible to implement a cast operator in Typescript?

After using JSWEET to transpile a large Java project, I noticed that it changed types such as Enumeration<Object> directly to Enumeration<any> in TypeScript. Previously in the Java environment, it was possible to assign an array Object[] to an ...

Angular 8 directive for concealing phone numbers

I am currently facing an issue with my phone mask directive that is designed to accept US format phone numbers. The problem arises when I try to clear the input by deleting one character at a time using the backspace key, as the value in the input field do ...

Is it possible to make functions dynamically adapt their behavior based on the types of arguments passed to them?

Consider this intricate collection of functions: interface Succes<a> { kind: 'succes' value: a } interface Failure<e> { kind: 'failure' error: e } type Result<a, e> = Succe ...

Updating the view in AngularJS with a service to keep users engaged even when they are offline

I'm currently developing an application that requires the ability to detect when a user loses internet connection or is unable to reach the server. Various controllers and services should be able to check and update this status easily. I have successf ...

Using CKEditor5 to Capture and Edit Key Presses

I'm currently working on capturing input from a CKEditor5 within an Angular application using TypeScript. While I am able to successfully display the CKEditor and confirm its presence through logging, I am facing difficulties in capturing the actual i ...

Issue arises when fastify/websocket is being used and an argument of type '{ websocket: boolean; }' is not compatible or able to be assigned to a parameter

I am facing an issue with my new project that involves fastify and Typescript. The error I am encountering is as follows: Argument of type '{ websocket: boolean; }' is not assignable to parameter of type 'RouteShorthandOptions ...ts(2345) B ...

Transforming API data into a particular type using Typescript

I am looking to extract only specific properties from a given object. Can TypeScript interfaces be used to iterate through the data and eliminate unnecessary properties? Sample data: [ 0: { "original_language" : "en", "t ...

Tips for implementing a request timeout in Typeorm/Typescript

Today, when using Typeorm with Postgres, there seems to be an issue where the behavior of getManager().query(...) getRepository().createQueryBuilder(...).getMany() is causing it to wait indefinitely for a response. Is there a way to set a timeout for t ...

After filling a Set with asynchronous callbacks, attempting to iterate over it with a for-of loop does not accept using .entries() as an Array

Encountering issues with utilizing a Set populated asynchronously: const MaterialType_Requests_FromESI$ = SDE_REACTIONDATA.map(data => this.ESI.ReturnsType_AtId(data.materialTypeID)); let MaterialCollectionSet: Set<string> = new Set<s ...

Visual Studio is refusing to highlight my code properly, intellisense is failing to provide suggestions, and essential functions like go to definition are not functioning as expected

Due to a non-disclosure agreement, I am unable to share any code. However, I am experiencing an issue with Visual Studio not highlighting my code or allowing me to utilize its built-in tools. While I can rebuild the project, I cannot edit or access any fil ...

Validate that the input is an array

Looking for a way to determine if a function parameter is an array or not, and then process it accordingly. If the parameter is not an array, convert it into an array before performing the desired function. For example: interface employee { first: st ...

Guidelines for Organizing Angular Interface Files and Implementing Custom Type Guards

In my Angular 2 project, I am utilizing Interfaces and have implemented User Defined Type Guards: grid-metadata.ts export interface GridMetadata { activity: string; createdAt: object; totalReps: number; updatedAt: object; } grid.service.ts ... ...

How to utilize FileReader for parsing a JSON document?

I'm currently facing an issue while attempting to read and copy a JSON file uploaded by the user into an array. When using .readAsText(), the returned data includes string formatting elements like \" and \n. Is there a way to utilize FileRe ...

Anticipate that the function parameter will correspond to a key within an object containing variable properties

As I develop a multi-language application, my goal is to create a strict and simple typing system. The code that I am currently using is as follows: //=== Inside my Hook: ===// interface ITranslation { [key:string]:[string, string] } const useTranslato ...

VSCode mistakenly detecting Sequelize findOne and findAll return type as any inferences

I have a model defined using Sequelize as shown below: import { Sequelize, Model, BuildOptions, DataTypes } from 'sequelize'; interface User extends Model { readonly id: string; email: string; name: string; password_hash: string; reado ...

Exploring Nashorn's capabilities in parsing TypeScript

Recently, I came across a discussion suggesting that Nashorn in JDK 9 should have the capability to parse TypeScript. Excited to try it out, I attempted to use it like this: Parser parser = Parser.create(); CompilationUnitTree ...

Why is the input box not opening when I click on the edit icon?

Whenever the edit button is clicked, the input box does not open. After clicking on the edit option and then clicking on another input box, it will be changed to an input box. I want the input box to change when the edit option is clicked. ...

Tips for preventing CORS and SSL issues when using localhost

Attempting to log in with Google on my Svelte app involves sending a request to an Express server. However, I encounter different errors on different browsers. On Firefox, I receive a Cross-Origin Request Blocked: The Same Origin Policy disallows reading t ...

transforming a JavaScript array into an object

output: Array(5) [ "Samsung", "Iphone", "Nokia", "Xiomi", "Blackberry" ] another output: Array(5) [ Object { id: "Samsung", label: "Samsung" },Object { id: "Iphone", label: ...

Fixed-sized array containing union parameters

One of my programming utilities allows me to create a statically sized array: export type StaticArray<T, L extends number, R extends any[] = []> = R extends { length: L; } ? R : StaticArray<T, L, [...R, T]>; To verify its functionality, ...