What sets TypeScript apart is the distinction between types like `InstanceType<typeof MyClass>` and `: MyClass`

I have been pondering whether there is a distinction between using InstanceType to declare a type, or simply using the Class name.

For instance, considering the following class:

MyClass {

  public static foo: string = 'abc'

  public makeFoo() {
    // awesome maker
  }

}

When I need to create an instance of the class, it appears that there is no apparent difference between:

// inside some other Class
private myClassInstance: InstanceType<typeof MyClass> 
...
this.myClassInstance = new MyClass()

and

// inside some other Class
private myClassInstance: MyClass 
...
this.myClassInstance = new MyClass()

In my experience with VSCode, I haven't noticed any visible discrepancy in using either of the two. Nonetheless, I suspect there must be a difference, considering TS has incorporated InstanceType<>.

Does anyone know if there is indeed a distinction?

Answer №1

Is there a distinction that needs to be made?

No, there isn't a difference. However, the use of InstanceType is required in certain scenarios.


The purpose of the InstanceType helper type is because a class name can represent two things:

  • The class name as the constructor function at runtime.
  • The class name as the return type of the constructor function at compile time (including the constructor function's prototype and potentially some instance fields).

In TypeScript, when you define a class, you are defining both: the constructor function (and its type) and the type of the instances created from it (which includes the class methods and fields).

In the provided example, the declaration includes:

  • MyClass: an interface that encompasses the class methods and fields.
  • typeof MyClass: the constructor function (in this case referring to the runtime class).

Since no specific constructor function was specified, its type is

new () => MyClass</code, and you can obtain the type <code>MyClass
using InstanceType.


To illustrate with a practical scenario, envision creating a factory function (which generates instances of classes). An initial implementation might appear as follows:

declare function factory<T>(ctor: T): T;

class A { }

const res = factory(A);
//    ^ resulted in `res: typeof A`, not an actual instance type.

Although TypeScript doesn't raise an error, you're essentially instructing TypeScript to interpret res as the constructor function for A rather than an instance of A.

However, the following approach proves successful:

type Constructor = new (...args: any[]) => any;
    
declare function factory<T extends Constructor>(ctor: T): InstanceType<T>;

class A { }

const res = factory(A);
//    ^ yields `res: A`, as expected.

This success is due to InstanceType extracting the appropriate return type.

Playground

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

Tips for sending icons as properties in React using TypeScript

Recently diving into typescript, I embarked on a straightforward project. Within this project lies a sidebar component that comprises multiple sidebarNavigationItem components. Each of these Sidebar items consists of an Icon and Title, showcased below. Si ...

What is the appropriate directory to place the `typescript` package in order for WebStorm to recognize it?

According to the information on this webpage: The Configure TypeScript Compiler dialog box provides two options: Detect: WebStorm will look for a typescript package within the current project. If it finds one, it will use that package. Otherwise ...

Is it possible to export all types/interfaces from .d.ts files within multiple folders using index.ts in a React TypeScript project?

In my current React project, I am managing multiple configuration folders: -config -api/ |index.ts |types.d.ts -routes/ |index.ts |types.d.ts ... For example, in the api/index.ts file, I can import necessary types using import {SomeTyp ...

Ways to manage an interactive pricing structure chart in Angular?

In my application, users can choose from four different types of plans that are retrieved from the backend. Once a plan is selected, they are directed to a payment page. The pricing table page can be revisited, and if a user has already purchased a plan, t ...

Failed to retrieve values from array following the addition of a new element

Does anyone have a solution for this problem? I recently added an element to my array using the push function, but when I tried to access the element at position 3, it wasn't defined properly processInput(inputValue: any): void { this.numOfIma ...

Export full module as a constructor function

Imagine having a nodejs module where requiring it gives you a constructor function. Here's an example: var Mod = require("modulename"); var mod = new Mod(); mod.method(); Now, I want to create a .d.ts declaration file that can be imported and utiliz ...

Using Angular to make an API call within a JavaScript function

I am facing an issue when trying to call an API in a JavaScript function as shown below. The injected services (subService) and defined variables (formData) are not recognized in the JavaScript function, resulting in an error of undefined addSub. How can I ...

Having trouble assigning more than one custom named property in TypeScript for MUI v5 Palette

I am currently setting up multiple custom attributes to make future updates easier. Nonetheless, I'm encountering a challenge with implementing more than one custom property in MUI v5. TypeScript Error TS2717: Subsequent property declarations must hav ...

Just starting out with TypeScript and running into the error: "Cannot assign type 'null' to type 'User[]'"

Why is TypeScript giving me an error message here? const dispatch = useAppDispatch(); useEffect(() => { onAuthStateChanged(auth, (user) => { dispatch(getUser(user)); }); }, [dispatch]); Error: Argument of type 'User | nul ...

Using ngTemplateOutlet to pass ng-template to a child component in Angular 5

I am looking to develop a versatile component that can utilize custom templates for data rendering, while consolidating the business logic to prevent redundancy. Imagine this use case: a paginated list. The pagination logic should be housed within the com ...

Assign the onClick function to the decoration of a Vscode extension

When I click on a vscode decoration, I want to trigger a function. Here's the code I created for this: const decoration = { range, hoverMessage: `${command} ${input}`, command: { title: 'Run Function', command: ' ...

The data type 'string | null | undefined' cannot be assigned to the data type 'string | undefined'

In my Angular application using Typescript, I have the following setup: userId?: number; token?: string; constructor(private route: ActivatedRoute) { this.route.queryParamMap.subscribe( (value: ParamMap) => { this.userId = val ...

Ways to address a buffered data problem in Websocket Rxjs. When trying to send a message, it is not being received by the server and instead is being stored in a

Currently, I am utilizing Websocket Rxjs within my application. The connection is successfully established with the server, and upon subscribing to it, all data is received in an array format. However, when attempting to send data back to the server, it se ...

Having an issue with forkJoin where the code seems to get stuck and does not continue execution after

The following script is retrieving two values from the database. I am using forkJoin for this purpose, which is a new approach for me. The reason behind utilizing this method is that there is a specific function that requires both values to be fetched bef ...

Using Material UI Slider along with Typescript for handling onChange event with either a single number or an

Just diving into Typescript and encountered an issue with a Material UI Slider. I'm trying to update my age state variable, but running into a Typescript error due to the typing of age being number and onChange value being number | number[]. How can I ...

By specifying the union type being used, the TypeScript compiler is informed

Imagine I have the following type: type TMyType = { a: string; b: number; c: number; d?: SpecialTypeA | SpecialTypeB | SpecialTypeC; } How can I specify in typescript that I am aware of the type of d in my (React) child components? I am hoping f ...

Definition file for Typescript Angular 1.5 component

Encountering a problem with typescript and angular 1.5 - when building, an error pops up saying error TS2339: Property 'component' does not exist on type 'IModule'.. Could it be that I overlooked a definition file containing this proper ...

Creating a class array with a specific number of elements in Angular

Is there a way to initialize an array of type Passenger with a number of elements equal to the value stored in the variable count, all within the ngOnInit() function? Here is the definition of the Passenger model: export class Passenger { constructor ...

React Bootstrap Forms: The <Form.Control.Feedback> element is failing to display when the validation is set to false

Problem: I am facing difficulties with displaying the React Bootstrap <Form.Control.Feedback></Form.Control.Feedback> when the validation is false in my form implementation. Steps to Recreate: Upon clicking the Send Verification Code button, ...

Inheritance of Generic Types in TypeScript

Could someone assist me in understanding what is incorrect with the code snippet provided here? I am still learning Typescript. interface ICalcValue { readonly IsNumber: boolean; readonly IsString: boolean; } interface ICalcValue<T> ex ...