TypeScript focuses on checking the type of variables rather than their instance

Is there a way to pass a type (not an instance) as a parameter, with the condition that the type must be an extension of a specific base type?

For example

abstract class Shape {
}

class Circle extends Shape {
}

class Rectangle extends Shape {
}

class NotAShape {
}

class ShapeMangler {
    public mangle(shape: Function): void {
        var _shape = new shape();
        // mangle the shape
    }
}

var mangler = new ShapeMangler();
mangler.mangle(Circle); // should work.
mangler.mangle(NotAShape); // should not work.

I think I might need to substitute shape: Function with something else. Is this achievable in TypeScript?

Note: It's important for TypeScript to acknowledge that shape has a default constructor. In C#, the equivalent would be...

class ShapeMangler
{
    public void Mangle<T>() where T : new(), Shape
    {
        Shape shape = Activator.CreateInstance<T>();
        // mangle the shape
    }
}

Answer №1

Consider two possible approaches:

class ShapeMangler {
    public mangle<T extends typeof Shape>(shape: T): void {
        // manipulate the shape
    }
}

Alternatively,

class ShapeMangler {
    public mangle<T extends Shape>(shape: { new(): T }): void {
        // manipulate the shape
    }
}

Both of these methods are compatible with the compiler:

mangler.mangle(Circle);
mangler.mangle(NotAShape);

In the provided example, your classes are empty, allowing an empty object to match any other structure.
If a property is added, like so:

abstract class Shape {
    dummy: number;
}

Then, using the method with ‘NotAShape’ will result in an error:

mangler.mangle(NotAShape); // Error

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

Using keyof on an indexed property within a generic type in Typescript does not effectively limit the available options

Imagine having an interface structure like this: export interface IHasIO { inputs: { [key: string]: string }, outputs: { [key: string]: string } } The goal is to develop a function that adheres to this interface as a generic type and ensur ...

Utilizing nested namespaces for optimal organization and clarity

Is it possible to export a namespace A with another namespace B nested within it? For example: // b.ts export namespace B { export const val = 'val'; } // a.ts export namespace A { //... some thing import B as namespace } --- the above wil ...

The promise briefly returns a placeholder object before resolving with the actual response

Currently, I am working on a simple check to determine whether myAnswer contains an answer. The checking functionality is operating smoothly; however, the issue arises in the final function that aims to return the string obtained from myAnswer. Instead of ...

Link a list separated by commas to checkboxes in Angular 9

Within my reactive form, I am binding a checkbox list to an array using the following structure: {id:number, name:string}. TS ngOnInit(): void { this.initFCForm(); this.addCheckboxes(); } initFCForm(): void { this.fcForm = this.formBuilder.group({ fr ...

Sending the route path to the child component

<Route path="/pointandclick"> <MyComponent /> </Route> Is there a way for MyComponent to retrieve the path of the Route that was accessed in the code above? To clarify, if I want to determine the specific ...

Using TypeScript generics to efficiently differentiate nested objects within a parsed string

Consider the following type code: const shapes = { circle: { radius: 10 }, square: { area: 50 } } type ShapeType = typeof shapes type ShapeName = keyof ShapeType type ParsedShape<NAME extends ShapeName, PROPS extends Sh ...

Having trouble with the Angular Language Service extension in VS Code for Angular-16?

Upon transitioning to Angular 16, I encountered errors while attempting to edit the components HTML due to the malfunctioning of the Angular Language Service extension. [Info - 09:41:11] Angular language server process ID: 18032 [Info - 09:41:11] Using t ...

What advantages does utilizing Jasmine Spy Object provide in Angular Unit Testing?

I have a question regarding unit testing in Angular using Jasmin/Karma. Currently, I am working with three services: EmployeeService, SalaryService, and TaxationService. The EmployeeService depends on the SalaryService, which is injected into its constru ...

Handlebar files are not compatible with Typescript loading capabilities

I am encountering an issue with my directory structure as follows : src |- server |- myServer.ts |- views |- myView.hbs dist |- server |- myServer.js The problem lies in the fact that the dist folder does not have a views subfolder, where the J ...

What could be causing my code to not run after subscribing to the observables?

In my code, I have two methods that return two lists: one for accepted users and the other for favorite users. The first part of my code works well and returns both lists, but in the second part, I need to filter out the accepted users who are also on the ...

Tips for sending information back to the previous screen in React Native Navigation version 5

Recently, I upgraded to react native navigation version 5 and now I am facing an issue with sending data back to the previous screen when making a goBack() call. To navigate to the next view, I use: const onSelectCountry = item => { console.log(it ...

How can I modify the icon once the accordion summary is expanded?

How can I switch the icon based on whether the accordion is expanded or not? I noticed that on the material ui page there is a CSS class called .Mui-expanded which can detect whether expanded={true} or false. But, how do I utilize this to change the ...

How can Typescript generics verify the value type for a specific key in a generic object?

I am facing an issue with a function called sortData. This function takes in a key and is designed to sort an array of objects based on the values for that key: function compare(v1: string | number, v2: string | number) { return (v1 < v2 ? -1 : v1 > ...

Accessing HTTP data through a function instead of using ngOnInit in Angular is a more efficient approach

Trying to retrieve data from a service using setInterval has posed an issue for me. When I call the service from ngOnInit, everything functions as expected. However, when attempting to call it from any other function, an error occurs: "ERROR TypeError: Ca ...

Implement a global interceptor at the module level in NestJS using the Axios HttpModule

Is there a way to globally add an interceptor for logging outgoing requests in Angular? I know I can add it per instance of HttpService like this: this.httpService.axiosRef.interceptors.request.use((config) => ...) But I'm looking to add it once a ...

Tips for utilizing array.items in joiful validation?

Can someone provide an example code or a link on how to correctly use the joyful validation for array items? I attempted the array.items validation code using joyful, but I am not sure how to specify the items. Thanks in advance! ...

Exclude specific fields when updating a document in Firebase using the update()

Currently, I am storing a class in Firebase by using the update() function. Is there a way to stop specific fields (identified by name) of the object from being saved to the Firebase database? It's similar to how we use the transient keyword in Java ...

How to correct placeholder text display in the input of a Material UI text field

Currently, I am utilizing the material ui text field component. The issue at hand is that when the text field is in focus, the placeholder shifts to the top of the field. https://i.stack.imgur.com/P5flf.png I prefer for the placeholder to remain within ...

typescriptExtract generic type from TypedDocumentNode<MyType, unknown> using introspection

I am currently utilizing a library that allows me to retrieve the type from a returned variable within a function. const myVar = gql(somestring) // The library function is called gql type myVarType = typeof myVar // The resultant value of myVarType is Typ ...

Are the missing attributes the type of properties that are absent?

I have a pair of interfaces: meal-component.ts: export interface MealComponent { componentId: string; componentQuantity: number; } meal.ts: import { MealComponent } from 'src/app/interfaces/meal-component'; export interface Meal { ...