Retrieve the instance type using a static method in TypeScript

Is it possible to name the currently class's instance type within a static method in a base class?

In other words, can you ensure type checking in the following code:

class Base {
  static addInitializer(i: (v: any /* What type would go here? */) => void) {
    // implementation is irrelevent
  }
}

class Dog extends Base {
  bark() {}
}

class Fish extends Base {
  swim() {}
}

Dog.addInitializer((dog) => {
  dog.bark();
  // @ts-expect-error
  dog.swim();
});

Fish.addInitializer((fish) => {
  fish.swim();
  // @ts-expect-error
  fish.bark();
});

Note the use of // @ts-expect-error before lines that should be a type error. This is due to the fact that v has type any rather than the desired named type.

TypeScript playground link

Answer №1

When you make the static method generic and constrain it by the this parameter of the static method, you allow the type of the class on which you are calling the static method to be accessible. To achieve this, simply utilize the InstanceType operator as shown below:

class Parent {
  static customize<T extends new (...args: any) => Parent>(this: T, customization: (instance: InstanceType<T>) => void) {
    // implementation details are irrelevant
  }
}

class Cat extends Parent {
  purr() {}
}

class Bird extends Parent {
  chirp() {}
}

Cat.customize((cat) => {
  cat.purr();
  // @ts-expect-error
  cat.chirp();
});

Bird.customize((bird) => {
  bird.chirp();
  // @ts-expect-error
  bird.purr();
});

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

Challenges in Displaying Components in React with Typescript

I'm currently facing an issue where the content I am trying to render on my screen is not appearing. Although the function correctly enters the if conditional statement, as confirmed by console logging. This is the section where I have implemented th ...

disappearing of vue event on single file component HTML element

I'm currently working on an ElectronJs project with Electron Forge, using the Webpack + Typescript template project In addition to that, I've integrated Vue and vue-loader for webpack in order to utilize Single File Component (SFC) files: { ...

Typescript error encountered in customized PipeLine class

I am currently developing a web scraping application using Puppeteer. In this project, I aim to create a PipeLine class that will take the current instance of the page and expose an add method. This add method should accept an array of functions with the t ...

Can we ensure type safety for the options of method decorators?

Exploring the creation of utility decorators like memoize and rateLimiter, I aim to maximize type safety while minimizing unnecessary boilerplate code. Can decorators maintain full type safety without explicitly defining generics? type GET_FUNCTION_SIGNA ...

Attempting to showcase information on the Angular frontend

When attempting to retrieve the Street name, I am seeing [object Object]. What is the optimal approach for displaying JSON data on the client side? I managed to display a street name but struggled with other components. How can I access the other elements ...

Tips for importing a non-namespaced module TypeScript definition into my custom types

When working with my custom types, I want to utilize the GraphQLSchema from the graphql module. If I simply write: interface MyThing { schema: GraphQLSchema } It doesn't reference the actual GraphQLSchema definition from the module (it's just ...

Attempting to convert numerical data into a time format extracted from a database

Struggling with formatting time formats received from a database? Looking to convert two types of data from the database into a visually appealing format on your page? For example, database value 400 should be displayed as 04:00 and 1830 as 18:30. Here&apo ...

The combination of TypeScript decorators and Reflect metadata is a powerful tool for

Utilizing the property decorator Field, which adds its key to a fields Reflect metadata property: export function Field(): PropertyDecorator { return (target, key) => { const fields = Reflect.getMetadata('fields', target) || []; ...

What is the best way to organize an array both alphabetically and by the length of its elements?

Imagine I am working with an array like this: ['a', 'c', 'bb', 'aaa', 'bbb', 'aa']. My goal is to sort it in the following order: aaa, aa, a, bbb, bb, c. this.array= this.array.sort((n1, n2) => ...

A step-by-step guide on accessing the data from an uploaded JSON file in a React application

One exciting feature is the drag and drop component that allows users to add multiple files. However, there seems to be an issue with displaying the content of a JSON file once it's added. Below is the code snippet in question: if (files?.length) ...

Unable to grab hold of specific child element within parent DOM element

Important Note: Due to the complexity of the issue, the code has been abstracted for better readability Consider a parent component structure like this: <child-component></child-component> <button (click)="doSomeClick()"> Do Some Click ...

`How can I effectively test a React.js page utilizing both Context and useEffect?`

I'm struggling with testing a page that uses Context and useEffect with Jest and Testing-library, can you offer any assistance? REPOSITORY: https://github.com/jefferson1104/padawan Context File: src/context/personContext.tsx import { createContext, ...

Distinguishing between type assertion of a returned value and defining the return type of a function

What distinguishes between performing a type assertion on a function's return value and explicitly typing the return value in the function signature? Let's consider only simple functions with a single return statement. interface Foo { foo: numbe ...

Guide on Implementing a Function Post-Rendering in Angular 2+

I'm looking to implement some changes in the Service file without modifying the Component.ts or directive file. Here's what I need: 1) I want to add an event listener after the service renders its content (which is generated by a third-party tool ...

Saving navigation paths in database

Is there a way to store routes in a database? For example: const routes: Routes = [ { path: 'url-of-component, component: ABCComponent } Can ABCComponent be stored in a mySQL database? Alternatively, how can I link the component to its path ...

How to transfer a parameter in Angular 2

I am currently facing a challenge in passing a value from the HTML file to my component and then incorporating it into my JSON feed URL. While I have successfully transferred the value to the component and displayed it in the HTML file, I am struggling to ...

The error states that the type '() => string | JSX.Element' cannot be assigned to the type 'FC<{}>'

Can someone help me with this error I'm encountering? I am fairly new to typescript, so I assume it has something to do with that. Below is the code snippet in question: Any guidance would be greatly appreciated. const Pizzas: React.FC = () => { ...

Tips for effectively utilizing Mongoose models within Next.js

Currently, I am in the process of developing a Next.js application using TypeScript and MongoDB/Mongoose. Lately, I encountered an issue related to Mongoose models where they were attempting to overwrite the Model every time it was utilized. Here is the c ...

Angular loop using an HTTP GET request is producing garbled information

Currently, I have a loop that includes an http GET request. This is the sample loop code: for (let index = 0; index < datas.length; index++) { let car = datas[index].smiles; console.log('or--> ' + car); this.subscr = this.CarServ ...

Investigating TypeScript Bugs in Visual Studio Code

As I navigate through various sources, I notice that there is a plethora of information available on older versions of VSCode (v1.16.1 - the most recent version at the time of writing) or deprecated attributes in the launch.json file. I have experimented ...