Ways to verify the existence of a property if obj is one of the specified types

Suppose I have a few interfaces A, B, C that implement a common Base.

interface Base {
    x: number;
    y: number;
    z: number;
}

interface A extends Base {
    a: true;
}

interface B extends Base {
    b: true;
}

interface C extends Base {
    c: true;
}

There is a function with if statements:

function foo(arg: A|B|C){
    if(arg.a!==undefined){//throws type error
        //do stuff for type a
    } else if(arg.b !== undefined){//throws type error
        //do stuff for type b
    } else if(arg.c !== undefined){ //throws type error
        //do stuff for type c
    }
}

What is the proper way to check if property exists without using any type? Is //@ts-ignore the only option?

Answer №1

When using Typescript, access to properties that are not common to all members of a union is restricted. This means you won't be able to directly access those non-common properties.

An alternative approach is to use an in type guard to check for the existence of a specific property in the union.

interface Base {
    x: number;
    y: number;
    z: number;
}

interface A extends Base {
    a: true;
}

interface B extends Base {
    b: true;
}

interface C extends Base {
    C: true;
}

function foo(arg: A|B|C){
    if('a' in arg){
        arg.a
    } else if('b' in arg){
        arg.b
    } else { 
        arg.C
    }
}

Answer №2

If you want to differentiate between types, consider using a custom type guard:

function isTypeA(arg: A | B | C): arg is A {
    return (<A>arg).a !== undefined;
}

function isTypeB(arg: A | B | C): arg is B {
    return (<B>arg).b !== undefined;
}

function handleTypes(arg: A | B | C) {
    if (isTypeA(arg)) {
        // do something for type A
    } else if (isTypeB(arg)) {
        // do something for type B
    } else {
        // do something for type C
    }
}

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

Can you explain the significance of the 'p' parameter in the p5.js code function for sketch-rnn?

The repository does not appear to include any code that defines the variable p, which leaves me uncertain about its purpose. What is the significance of the 'p' parameter in the function, and why is it needed? The general structure of the code i ...

Creating a dynamic calendar application with Angular 2 using PrimeNG components

After diving into PrimeNG, I diligently followed the instructions on their documentation to get everything set up. However, my UI ended up looking quite odd, similar to the image below. Does anyone have any insight as to why this might be happening? Here ...

Ways to restrict the values allowed in a TypeScript type?

I have a requirement: type AllowedKeys = 'a' | 'b' | 'c' ... and now I want to define a type where the key has to be one of the values in AllowedKeys. For example: type MyType = { a: number; b: string; c: boolean; d: {} / ...

Merging arrays from observables without the need to wait for all of them to finish

Within my application, I have established a process where data is fetched from a remote server at regular intervals. The retrieved data is structured as an array of objects and is then showcased in the HTML template using the angular async pipe. To enabl ...

What is the solution for resolving the error message "IResponse not found" in Apollo Client?

Here are all the errors that need to be addressed: ERROR in [at-loader] node_modules/apollo-client/transport/afterware.d.ts:3:15 TS2304: Cannot find name 'IResponse'. ERROR in [at-loader] ...

Passing the array as query parameters and retrieving it using the angular getAll function is the most efficient way

When using this function, I extract the ids of items and aim to send them as an array for retrieval with getAll(). const queryParams: Record<string, string[]> = selectedItems.reduce( (acc, curr, index) => ({ ...acc, [&apo ...

Using the slice pipe on the data for a child component property is resulting in endless calls to the @Input set method

After incorporating a slice pipe into the data object below and passing that data to the child component's @Input method, there appears to be an endless loop of calls to that method. However, eliminating the slice pipe from the data object resolves th ...

Tips for binding a type that has been imported dynamically

Struggling to automatically link templates to an inversifyjs container, but all attempts have failed. Seeking assistance! private templates = [ {file: './component.html.tpl', obj: 'HtmlTemplate'}, {file: './component.tpl.t ...

Testing components in React involves creating or invoking specific construct or call signatures

Exploring this React component: import { Meta } from '@storybook/react'; export function MyComponentExample() { return ( <div>my component example</div> ); } export default { component: MyComponentExample, title: 'M ...

Understanding Mongodb: the process of populating a schema that is referenced within another schema using an API

Looking to make adjustments to my Api in order to populate a referenced schema. Here's the schema I am working with: export const taskSchema = new Schema ({ user:{ type: String, required: true }, project: { type ...

Utilizing Ionic Storage to set default request headers through an HTTP interceptor in an Angular 5 and Ionic 3 application

I'm attempting to assign a token value to all request headers using the new angular 5 HTTP client. Take a look at my code snippet: import {Injectable} from '@angular/core'; import {HttpEvent, HttpInterceptor, HttpHandler, HttpRequest} from ...

Expanding or overriding module type or interface properties using TypeScript declaration merging

Currently, I am utilizing the types from @types/react-router-dom version 4.3.1, which brings in types from both @types/react-router and @types/history. Within my application, I consistently have two properties in the location state that I would like to au ...

"Encountering a Type Error when using Ramda's propOr function in

Struggling with a typing issue in Typescript while using Ramda. Here's my dilemma: My code const podName = R.propOr(null, 'podName', node) as String | null error: TS2352:Type 'propOr_general_011' cannot be converted to type &ap ...

Cannot establish a connection with Socket.IO

I've encountered an issue with establishing a connection to Socket.IO in my node server. Although the server starts successfully with Socket.IO, I am not seeing any console logs when trying to connect to Socket. this.server.listen(this.port, () => ...

Error encountered in Angular 7.2.0: Attempting to assign a value of type 'string' to a variable of type 'RunGuardsAndResolvers' is not allowed

Encountering an issue with Angular compiler-cli v.7.2.0: Error message: Types of property 'runGuardsAndResolvers' are incompatible. Type 'string' is not assignable to type 'RunGuardsAndResolvers' This error occurs when try ...

The inability of rxjs map to infer types for the project function during overload can lead to type errors unless explicitly specified

I am struggling to make TypeScript happy in this particular case: const t1 = new BehaviorSubject("test"); const t2 = new BehaviorSubject(["test2"]); function transformString(subject:string):string function transformString(subject:strin ...

Guide to creating a personalized pipe that switches out periods for commas

I currently have a number with decimal points like --> 1.33 My goal is to convert this value so that instead of a dot, a comma is displayed. Initially, I attempted this using a custom pipe but unfortunately, it did not yield the desired result. {{get ...

Configuring eslint-import-resolver-typescript in a multi-package repository

I'm currently working on implementing path-mapping within a monorepo structure. Despite having existing eslint-plugin-import rules in place, I am encountering an error stating "Unable to resolve path to module" for all mapped imports. app/ ├─ pack ...

A better choice than Java's <? super SomeType> in Typescript

Is there a scenario in which one of the generic parameters used to create an instance of my class should be a superclass of another class? In Java, this is easily achievable using <? super SomeType>. What would be the equivalent in TypeScript? ...

Error: Unable to load the parser '@typescript-eslint/parser' as specified in the configuration file '.eslintrc.json' for eslint-config-next/core-web-vitals

When starting a new Next.js application with the specific configuration below: ✔ What name do you want to give your project? … app ✔ Do you want to use TypeScript? … No / [Yes] ✔ Do you want to use ESLint? … No / [Yes] ✔ Do you want to use T ...