Hierarchy: Obtain the parent of a specific type through type checking

I'm struggling with TypeScript's type checking system, especially when dealing with a composite that contains elements derived from a common base class. How can I create a function that recursively traverses the hierarchy to find and return the first ancestor of a specific type?

abstract class Employee
{
    public Superior: Employee;

    /** THIS IS NOT WORKING */
    public getSuperiorOfType<T extends Employee>( type: typeof T ): T
    {
        if (this instanceof T) return this;
        else if (this.Superior !== undefined) return this.getSuperiorOfType(type);
    }
}

class Manager extends Employee {}
class TeamLead extends Employee {}
class Developer extends Employee {}

let tom = new Manager();
let suzanne = new TeamLead();
let ben = new Developer();

ben.Superior = suzanne;
suzanne.Superior = tom;

let x = ben.getSuperiorOfType(Manager); // x = tom

Any assistance on this matter would be greatly appreciated...

Answer №1

  1. The declaration of 'class type' cannot be made using typeof T. The use of typeof in a type position is restricted to variables only, not types. To achieve this, you should utilize what is known as a constructor signature:

    public getSuperiorOfType<T extends Employee>(type: { new(...args: any[]): T}): T
    
  2. Attempting to verify if an object is an instanceof a generic type parameter will not work - instanceof T is ineffective because generic type parameters are not present at runtime. However, since you have the type as an actual function parameter, utilizing instanceof type may be successful.

  3. Your code lacks true recursion as each call to getSuperiorOfType is made on the same this object. In order to move up one level in hierarchy, you need to invoke it as

    this.Superior.getSuperiorOfType(...)
    .

    abstract class Employee
    {
        public Superior: Employee;
    
        public getSuperiorOfType<T extends Employee>(type: { new(...args: any[]): T}): T
        {
            if (this instanceof type) return this;
            else if (this.Superior !== undefined) return this.Superior.getSuperiorOfType(type);
        }
    }
    
    class Manager extends Employee {}
    class TeamLead extends Employee {}
    class Developer extends Employee {}
    
    let tom = new Manager();
    let suzanne = new TeamLead();
    let ben = new Developer();
    
    ben.Superior = suzanne;
    suzanne.Superior = tom;
    
    
    let x = ben.getSuperiorOfType(Manager); 
    console.log(x === tom); // true
    

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

How can TypeScript be used to remap an interface for a single element when destructuring an object?

In Typescript 3.4, when destructuring an object, you can define the exact response type like this: interface IResponse { loading: boolean; data: any; error: string; } interface IObject { ... } const {loading, data, error}:{data: IObject} = ...

Creating and incorporating a generator function within an interface and class: A step-by-step guide

In vanilla JavaScript, the code would look something like this: class Powers { *[Symbol.iterator]() { for(let i = 0; i < 10; i++) yield { i, pow: Math.pow(i, i) } return null; } } This can then be utilized in the following manner: co ...

The query fails to retrieve results for the specified date and the beginning of the month

I have encountered an issue with my query that is supposed to fetch values between the start and end of the month. Interestingly, when a record is entered on the first day of the month, it doesn't get returned in the query result. Only records entered ...

Encountering an issue with Nuxt 3.5.1 during the build process: "ERROR Cannot read properties of undefined (reading 'sys') (x4)"

I am currently working on an application built with Nuxt version 3.5.1. Here is a snippet of the script code: <script lang="ts" setup> import { IProduct } from './types'; const p = defineProps<IProduct>(); < ...

Tips for addressing style issues within innerText

I am trying to use PrismJS to highlight HTML code, but the inner text function doesn't recognize line breaks (\n). <pre class="language-markup background-code"><code [innerText]="getHtmlCode()""></code> I have been working wi ...

Display different text based on the property value

I need to display different text based on the value of a property, showing "offline" if camera.key is null and "online" otherwise. Here's the template I'm using: <h3>Camera sensors</h3> <table> <th>Name</th> ...

Can you explain how to incorporate async/await within the setup() function of Vue 3.0 using Typescript?

(This particular inquiry pertains to TypeScript, not JavaScript. Despite a resolved JavaScript query below, this issue remains specific to TypeScript). I am attempting to implement async functionality in Vue 3.0 using TypeScript. The following code opera ...

The Problem with TypeScript Union Types

I recently started using TypeScript and ran into an issue with a similar scenario. Despite my efforts, I encountered two errors that I can't seem to figure out. If anyone has any insights on how to resolve this, I would greatly appreciate the help! in ...

Angular Protectors: Stop unauthorized access to a URL while allowing authorized refresh

I've developed a Protection feature that blocks users from directly accessing a specific URL, and it's functioning correctly. However, the issue arises when I try to refresh the page as the Protection feature ends up redirecting me. Below is th ...

Combining Arrays Together in TypeScript

I am in need of a solution to merge two arrays into one using TypeScript. First Array Object: export interface Item{ Label : string, Code : string, Price : number, } Second Array Object: export interface Amou ...

Utilizing the "as" keyword for type assertion in a freshly created react application using create-react-app leads to the error message `Parsing error: Unexpected token, expected ";"`

After creating a new CRA project using yarn create react-app my-app --template typescript, I encountered an error when trying to run the development server with yarn start: src/App.tsx Line 5:24: Parsing error: Unexpected token, expected ";" ...

What is the best way to access automatically generated JavaScript variables in TypeScript?

I am currently facing an issue with integrating a Google login API in my React project and I need some help. The problem arises when the user already has an active session, rendering the API unnecessary. The Javascript solution provided is as follows: co ...

Error TS2694 is being caused by Electron Typescript Material-UI withStyles because the namespace "".../node_modules/csstype/index"" does not have an exported member called 'FontFace'

While I am experienced with Material-UI, I am relatively new to Electron and using React, TypeScript, and Material-UI together. Recently, I encountered an error while attempting to create an electron boilerplate code for future project initialization. Init ...

24-hour flatpickr timepicker

Can anyone assist me in setting my hour format to 24 hours instead of AM/PM in Angular? I've been struggling with it for the past 2 days. Below are my TypeScript and HTML code snippets: TypeScript: flatpickrOptions: any = { locale: French, enable ...

Is TypeScript designed to accommodate duck typing?

There seems to be conflicting information on this topic. https://basarat.gitbooks.io/typescript/content/docs/classes.html (go to the inheritance section) suggests that it's supported, but I'm encountering compilation issues with my TypeScript cod ...

What is the best way to send an array from Angular 6 to an ASP.NET Core API using the GET method?

When my Angular 6 app makes a request to the ASP.NET Core web API using the GET method, I want to send a list or array of unique identifiers as parameters. In return, I expect only information relevant to those identifiers to be retrieved from the API. He ...

Defining RefObject effectively in TypeScript

Greetings everyone, I am a newcomer to TypeScript and currently attempting to create a type for a RefObject that is of type HTMLAudioElement. However, I have encountered an error message. The error states: Type 'MutableRefObject<HTMLAudioElement> ...

Challenges in Power BI Custom Visual Development: Trouble setting height for div elements

Currently, I am working on creating a custom visual for Power BI that includes a leaflet map within a div element. However, the issue arises when I fail to set a specific height for the map, resulting in an empty visual. I have managed to set a fixed heigh ...

Create a tuple type that encompasses all possible paths within a recursive object configuration

Consider the following templates for 'business' types, representing compound and atomic states: interface CompoundState<TName extends string, TChildren extends { [key: string]: AnyCompoundState | AnyAtomicState }> { type: 'parent&ap ...

Is there a way to substitute the HOC with a single call and solely modify the prop?

One issue I've encountered in my project is the repetitive use of a Higher Order Component (HOC) for the header. Each time it's used, the props are set to determine whether header links should be displayed or not. My objective is to streamline th ...