Expanding the base class and incorporating a new interface

(Here is an example written using Typescript, but it applies to other cases as well)

class IMyInterface {
    doC:(any) => any;
}

class Common {
    commonProperty:any;

    doA() {
    }

    doB() {
    }
}

class ClassA extends Common {}
class ClassB extends Common implements IMyInterface {
    doC(test:any) {
        return true;
    }   
}


class Factory {
    myClass: Common;

    doSomething() {
        // Property 'doC' does not exist on type 'Common'
        this.myClass.doC('test');
    }
}

Classes A and B are extensions of the Common class. Therefore, in the Factory class, myClass can be defined as a type Common.

However, Class B needs to implement IMyInterface, which is not included in the Common class. This results in an error being thrown by the Factory class, indicating that the interface method does not exist on the Common class.

What would be the best way to address this?

[Edited]

First and foremost, @basarat, thank you very much for your input. I still have some lingering questions,

What if there are additional classes that also implement IMyInterface?

class ClassC extends Common implements IMyInterface {
    doC(test:any) {
        return true;
    }   
}
class ClassD extends Common implements IMyInterface {
    doC(test:any) {
        return true;
    }   
}
class ClassE extends Common implements IMyInterface {
    doC(test:any) {
        return true;
    }   
}

In such a scenario, one might consider defining the doC() method in the Common class. However, it is also important to ensure that Class B, C, D, and E all must implement the doC() method.

Please offer some guidance on this matter.

Answer №1

Can you advise on the best approach to tackle this issue?

In essence, you need to clarify that myClass is typically just Common, but in specific cases, it could be ClassB. This can be achieved by utilizing a union type along with a typeguard:

class Factory {
    myClass: Common | ClassB;

    doSomething() {
        const myClass = this.myClass;
        if (myClass instanceof ClassB){
            // it's valid!
            myClass.doC('test');    
        }
    }
}

Additional Information

Here is a complete example:

class IMyInterface {
    doC:(any) => any;
}

class Common {
    commonProperty:any;
    doA() {
    }
    doB() {
    }
}

class ClassA extends Common {}
class ClassB extends Common implements IMyInterface {
    doC(test:any) {
        return true;
    }   
}


class Factory {
    myClass: Common | ClassB;

    doSomething() {
        const myClass = this.myClass;
        if (myClass instanceof ClassB){
            // it's valid!
            myClass.doC('test');    
        }
    }
}

Documentation

For more information on Union types, visit: https://basarat.gitbooks.io/typescript/content/docs/types/type-system.html#union-type

To learn about Type Guards, refer to: https://basarat.gitbooks.io/typescript/content/docs/types/typeGuard.html

UPDATE

Upon request, if there is a need to check for the presence of the interface, a user-defined type guard must be created (refer to the documentation here: https://basarat.gitbooks.io/typescript/content/docs/types/typeGuard.html#user-defined-type-guards). Here's an example:

function isMyInterface(foo:any): foo is IMyInterface {
    return typeof foo.doC === 'function';
}

class Factory {
    myClass: Common | IMyInterface;

    doSomething() {
        const myClass = this.myClass;
        if (isMyInterface(myClass)){
            // it's valid!
            myClass.doC('test');    
        }
    }
}

The revised code will look like this:

class IMyInterface {
    doC:(any) => any;
}

class Common {
    commonProperty:any;
    doA() {
    }
    doB() {
    }
}

class ClassA extends Common {}
class ClassB extends Common implements IMyInterface {
    doC(test:any) {
        return true;
    }   
}
class ClassC extends Common implements IMyInterface {
    doC(test:any) {
        return true;
    }   
}
class ClassD extends Common implements IMyInterface {
    doC(test:any) {
        return true;
    }   
}
class ClassE extends Common implements IMyInterface {
    doC(test:any) {
        return true;
    }   
}

function isMyInterface(foo:any): foo is IMyInterface {
    return typeof foo.doC === 'function';
}

class Factory {
    myClass: Common | IMyInterface;

    doSomething() {
        const myClass = this.myClass;
        if (isMyInterface(myClass)){
            // it's valid!
            myClass.doC('test');    
        }
    }
}

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

Establish a user profile and define custom claims using Firebase Authentication

When a new user is registered, certain values for user access control are set up immediately. The issue arises when the data set is only visible in the subsequent sessions after logging out of the authenticated user session that was created. My challenge ...

When attempting to send an email with nodemailer, an error message popped up saying "setImmediate is not defined."

let transporter = nodemailer.createTransport({ host: "sandbox.smtp.mailtrap.io", port: 2525, auth: { user: "xxxxxx", pass: "xxxxxx" }, tls: { rejectUnauthorized: false } ...

Simplify an array in Javascript

I have a collection of objects structured in the following way: let list = [ { 'items': [ 'item 1', 'item 2' ] }, { 'items': [ 'item 3' ] } ] My goal is to flatte ...

Encountered an error stating 'name' property is undefined while using @input in Angular 2

Everything seems to be set up correctly, but I'm encountering an error in the browser console that says "Cannot read property 'name' of undefined": https://i.sstatic.net/TvfEr.png This is how my media.component.ts file is structured: impo ...

Assigning namespaces to a property of classes in typescript: A step-by-step guide

As I work on adding a declaration file to a TypeScript package, I encounter some syntax that looks like this: const Sequelize = require('Sequelize'); //... class Application { Sequelize = Sequelize; } To address this, I created a file named ...

React App Creation: Issue with ESLint configuration in TypeScript environment

I recently built a React app with the CRA (typescript template), but I noticed that TypeScript isn't adhering to the rules specified in the ESLint configuration. This is puzzling because I have consistently used this configuration in all my React proj ...

Update ngModel value following the PUT request response

I currently have a variable named dummy_value and I would like to update it using an input box. <p>{{dummy_value}}</p> <input [(ngModel)]="dummy_value" /> Upon making this change, the dummy_value updates instantly due to the two-way bin ...

The most efficient and hygienic method for retrieving a value based on an observable

Looking at the structure of my code, I see that there are numerous Observables and ReplaySubjects. When trying to extract a value from one of these observables in the HTML template, what would be the most effective approach? In certain situations, parame ...

Guide to adding jquery with typings installation

Need assistance: typings install jquery --global typings ERR! message Unable to find "jquery" ("npm") in the registry. Did you want to try searching another source? Also, if you want contribute these typings, please help us: https://github.com/typings/re ...

Updating the value of a variable in a separate file with Node.js

I'm facing a business scenario that can be likened to a challenging situation. To simplify, here's the problem: File1.ts import * from 'something'; export const var1="value of var1"; //assume there is a variable 'x' ...

The most accurate type to determine after verifying that `typeof a === 'object' && a !== null` is the following

Within my codebase, there exists an assertion function that verifies a given value is an object (using the typeof operator), with the exception of null: export function assertIsJavaScriptObjectExceptNull(value: unknown) { if (typeof value !== 'obj ...

Error encountered in Angular CLI: Attempting to access property 'value' of an undefined variable

I am encountering an issue while trying to retrieve the values of radio buttons and store them in a MySql database. The error message I receive is TypeError: Cannot read property 'value' of undefined. This project involves the use of Angular and ...

Encountering Duplicate Identifier Error while working on Angular 2 Typescript in Visual Studio Code

Currently attempting to configure a component in Angular 2 with Typescript using Visual Studio Code on Mac. Encounter the following errors when trying the code below: duplicate identifier 'Component'. and Duplicate identifier' DashboardCompo ...

Exploring the Prototype-based programming concept in JavaScript

I am determined to deepen my understanding of JavaScript and explore what lies beneath its surface. While I have delved into various guides on the Object-Oriented Paradigm with Prototypes in JavaScript, I am struggling to comprehend how this paradigm diffe ...

Guide to specifying the indexer type of a function argument as T[K] being of type X in order for t[k]=x to be a permissible expression

Currently, I am attempting to create a function that can alter a boolean property within an object based on the provided object and property name. While I have found some helpful information here, the function body is still producing errors. Is there a way ...

Utilizing a forwardRef component in TypeScript to handle child elements

Working with @types/react version 16.8.2 and TypeScript version 3.3.1. This forward refs example was taken directly from the React documentation with added type parameters: const FancyButton = React.forwardRef<HTMLButtonElement>((props, ref) => ...

What steps are involved in setting up a SAML service provider using @node-saml/node-saml?

I'm currently working on a SAML SP implementation using the @node-saml/node-saml library. Despite creating the necessary source code, I am facing an issue with the SAML authentication not functioning as expected. Can anyone provide guidance on how to ...

Encountering difficulties in generating a personalized Angular Element

Currently, I am in the process of developing a custom Component that needs to be registered to a module. Here is how it is being done: app.module.ts import { createCustomElement } from "@angular/elements"; @NgModule({ declarations: [ExtensionCompone ...

Having trouble importing d3.js and typescript in IntelliJ?

Encountering errors in browsers' console when utilizing d3.select() in typescript code. Despite trying alternative methods like d3-timer.now(), the issue persists. As a newcomer to typescript, I am utilizing intelliJ Ultimate 2019.1. Through npm, I h ...

Gain insights on Stripe Webhooks with Firebase Functions and Node.js

I've been struggling to integrate Firebase functions with Stripe webhooks for listening to events. Take a look at my code: exports.stripeEvents = functions.https.onRequest((request, response) => { try { const stripeSignature = request. ...