Define the static property as an array containing instances of the same type

I created a class called Foo with a static property named instances that holds references to all instances. Then, I have another class called Bar which extends Foo:

class Foo {
    static instances: Foo[];

    fooProp = "foo";

    constructor() {
        let ctor = this.constructor as typeof Foo;
        ctor.instances.push(this);
    }
}

class Bar extends Foo {
    barProp = "bar";
}

The issue arises because the type of Bar.instances is Foo[] instead of Bar[], resulting in the following error:

let foo = new Foo();
let bar = new Bar();

Foo.instances[0].fooProp; // works
Bar.instances[0].barProp; // Property 'barProp' does not exist on type 'Foo'. ts(2339)

I attempted using InstanceType<this> for the type of instances, but encountered an error:

class Foo {
    static instances: InstanceType<this>[]; // A 'this' type is available only in a non-static member of a class or interface. ts(2526)
    ...
}

This seems to be related to an issue discussed in the TypeScript repo about polymorphic behavior. Is it currently impossible to achieve what I want to do, or am I missing something?

Check out the playground link here.

Answer №1

The error has been successfully identified by TypeScript. In this scenario, the static instances array will contain instances of both Foo and Bar.

To see this in action, add the following code to your example and check the console for logs:

console.log(Foo.instances[0] instanceof Foo); // true
console.log(Foo.instances[0] instanceof Bar); // false, barProp will not be available on this instance

console.log(Foo.instances[1] instanceof Foo); // true
console.log(Foo.instances[1] instanceof Bar); // true, barProp will be 'bar'

Playground link

If you want to store all instances of Foo in one array and all instances of Bar in another, you should override the static instances property in the Bar class:

class Bar extends Foo {
    static instances: Bar[] = []

    barProp = 'bar';
}
console.log(Foo.instances.length); // 1
console.log(Foo.instances[0].fooProp); // 'foo'

console.log(Bar.instances.length); // 1
console.log(Bar.instances[0].barProp); // 'bar'

Playground link

Answer №2

Simply put, just because a Bar is an extension of Foo does not alter the data types of already defined variables. For example, the static variable 'instance' will remain as type Foo[] as specified in your Foo class. Using 'this' may not be effective in this scenario since 'this' typically refers to an object, and within a static context, there is no specific object for it to reference.

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

A guide to sending epoch time data to a backend API using the owl-date-module in Angular

I have integrated the owl-date-time module into my application to collect date-time parameters in two separate fields. However, I am encountering an issue where the value is being returned in a list format with an extra null value in the payload. Additiona ...

Having trouble getting Angular 8 WebRTC to function properly on two tabs

I've been tasked with creating an audio chat room for 2 users. Initially, I used the following app example: Peer connection: audio only After converting the code to TypeScript, it successfully ran: Stackblitz However, I'm facing challenges ge ...

Exploring the power of global injectors in Angular 7 for component inheritance

Recently, I have been following a method outlined in a blog post on MSDN to simplify the extension of components without having to include all dependencies in the super() call. However, this approach seems to have ceased working in Angular 7 with Typescrip ...

Is Typescript capable of identifying void functions automatically?

Being new to Typescript and programming in general. Instead of using: function greet(greeting: string): void; Can I simplify it like this? Is there any type inference? function greet(greeting: string); ...

Unable to initialize the ng2-admin Angular2 Bootstrap template on a Go server due to a failed download attempt

Hello everyone, I am a newcomer to this forum and have limited experience with Angular2 and Golang. I am currently facing an issue as I want to experiment with a template on a Go server. To tackle this, I created a main.go file that includes the followin ...

What is the recommended data type for Material UI Icons when being passed as props?

What specific type should I use when passing Material UI Icons as props to a component? import {OverridableComponent} from "@mui/material/OverridableComponent"; import {SvgIconTypeMap} from "@mui/material"; interface IconButtonProps { ...

Passing a type as an argument in Typescript

How can I pass a type as a parameter in Typescript? type myType = {} const passingType = (t: Type) => { const x : t = {} } passingType(myType); I keep receiving TypeScript errors. 't' is referencing a value, but it is being used as a t ...

Issue with type narrowing and `Extract` helper unexpectedly causing type error in a generic type interaction

I can't seem to figure out the issue at hand. There is a straightforward tagged union in my code: type MyUnion = | { tag: "Foo"; field: string; } | { tag: "Bar"; } | null; Now, there's this generic function tha ...

How come I am unable to fetch classes and enums from a namespace?

When using Typescript with pg-promise, I am facing an issue where I can't import the classes and enums as I normally would. Typically, when working with a library, I import a type, use it, and everything functions properly. However, in the snippet bel ...

Implementing a props interface for conditions in styled components within a React application using Typescript

This specific component is created using React along with the "styled components" library to manage user input. In the case of invalid user input, the corresponding styles should be displayed as shown below (class invalid). Although this example functions ...

Developing an asynchronous function to retrieve data from an external API utilizing Await/Async strategy

Currently, there is a method under development that retrieves a value from the API. What steps are needed to properly integrate Async/Await functionality into this process? fetchAccountById(){ let accountName; this.accountService.fetchDa ...

Setting up a Typescript project with a shared package configuration

Before I begin, there are a few premises to consider: I require a shared package that will be included in three other packages, TypeScript, Only one node modules, Ability for multiplatform usage (Windows / Linux), To utilize dependencies from the shared ...

Combining Several Middleware Functions in NextJs 13 for Authentication and Localization

Important Note If you are interested in exploring my code further, you can find the repository here. To access the specific code for the ott-platform, navigate to apps/ott-platform. Please make sure to create an account on Clerk and input your Clerk key i ...

Angular project service file experiencing issues with TypeScript string interpolation functionality

Here is the code snippet for a service in an Angular project: @Injectable() export class FetchDataService { fetch(link){ console.log('This is a ${link}'); } } In my component, I am invoking this method with a string parameter. Upon che ...

Activate expansive pop-up windows with primeng's dynamic dialog feature

In my Angular web application, I am using the PrimeNg modal extension to display modal popups. I have successfully passed a component to the modal service with the following code: const ref = this.dialogService.open(LogsComponent, { data: { ...

Tips for transfering variables from an electron application to the backend of an Angular project

My goal is to develop a website and desktop application using the same code base. However, due to some minor differences between the two platforms, I need a way for my Angular app to distinguish whether it has been called from the web or from Electron. I& ...

Place the cursor at the conclusion of the text box

I am working on creating a user input form for chat messaging and I need some help. Here is the HTML-code snippet that I am currently using: HTML-code Currently, when the user presses ENTER, I retrieve the text from the textbox and save it. If the user ...

"Encountering Devextreme Reactive Errors while navigating on the main client

Attempting to integrate Devextreme with Material Ui in my Typescript React app has been a challenge. Despite following the steps outlined in this documentation and installing all necessary packages, I am encountering issues. I have also installed Material ...

mat-table dataSource is not functioning properly with REST API integration

I'm facing an issue while trying to populate a Material Table with data. My model Block has fields such as id, date, etc. The API call is made in data.service and the function getAllBlock() fetches the blocks. I tested this in the app.component.html ...

React - Error: Unable to access the 'props' property because it is undefined

I am working on implementing a click event to delete an item from my list, but I keep encountering the error message "TypeError: Cannot read property 'props' of undefined" whenever I click on it. Although I am striving to follow ES6 standards as ...