Using a static class reference as a parameter in a generic type leads to a error

Before I submit a ticket on github, I want to double-check that I'm not making any mistakes. The issue should be clear enough:

class A {}

class B {
  static A = A;
}

function foo<T>(arg: T) {}

// this is valid
const b = new B.A;

// "B" only refers to a type, but it's being used as a namespace.
foo<B.A>(1);

Am I correct in assuming that I can reference a type like this?

While the instantiation deduces the types correctly as:

b = A
B.A = typeof A
B = B

It gives this inference for the last line:

B = any

As a result, VS Code can navigate to the definition for the first one, but struggles to find references for the second.

This appears quite strange to me.

UPDATE: The initial response I received turned out to be incorrect, as this syntax results in a typeof of a typeof:

// arguments of type "A" cannot be assigned to parameters of type "typeof A", property "prototype" is missing.
foo<(typeof B)['A']>(b);

Even if I specify an explicit constructor type, things only get more complicated:

// this will make things worse
class B {
  static A: { new (): A } = A;
}

Answer №1

Is it possible to reference a type in this manner?

In TypeScript, no.

For instance:

class A {}

class B {
  static A = A;
}

You can only utilize B.A as a value and not as a type. It might be misleading since classes in TypeScript can function both as values and types, but this is exclusive to classes, with other entities behaving differently.

As for B.A, it serves as a value where the actual value represents class A, and the type of this value would be typeof A (using a class in a type position results in typeof A, utilized for types and not values).

If you intend on using the type of B.A as a generic type parameter, you can do so by:

a<(typeof B)['A']>(A);

Explanation: A exists within the static aspect of the B class. You reference the static aspect of a class via typeof B, and you refer to a member type using [], which signifies an indexed access type operator.

The function a mentioned earlier accepts a constructor of class A. Should you desire for function a to accept an instance of A, the declaration of B.A should be altered as follows:

class A {}

class B {
  static A: A;
}

This version will compile successfully.

a<(typeof B)['A']>(new A());

UPDATE

If initializing B.A to A's constructor while retaining access to the instance side of A is your goal, you must wait until TypeScript 2.8. Once available, there's a feature that allows extracting the instance type from the constructor type - the following code will compile after running npm i typescript@next:

class A {}

class B {
  static A = A;
}

function a<T>(a: T) { }

const b = new B.A;

type Constructor<T> = { new(...args: any[]): T };

type Instance<C> = C extends Constructor < infer T > ? T : never;

a<Instance<(typeof B)['A']>>(b);

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

Error message: "IAngularStatic type does not have property IScope" caused by Typescript Directives

I'm working on creating an Angular Directive using TypeScript to share a scope item. I created an interface that inherits from ng.IScope, but Visual Studio Code is showing me a warning: "Property IScope does not exist on type IAngularStatic". I am usi ...

Encountering a Javascript error while trying to optimize bundling operations

After bundling my JavaScript with the .net setting BundleTable.EnableOptimizations = true;, I've encountered a peculiar issue. Here's the snippet of the generated code causing the error (simplified): var somVar = new b({ searchUrl: "/so ...

Using an array of objects as a data source for the Material Angular table

My user data is causing some issues and looks like this... [{"firstName":"Pinkie","lastName":"Connelly","username":"Darlene.Marvin","email":"<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="19506a767b7c75464b7c77777c6b5971766d74 ...

Error encountered with TypeScript template literals strings type

There's a new feature in the latest version of Typescript that allows the use of template literal strings as types, like this: type Hey = 'Hey'; type HeyThere = `${Hey} There`; It works perfectly in the Typescript playground with version 4 ...

Tips for eliminating unicode characters from Graphql error messages

In my resolver, I have implemented a try and catch block where the catch section is as follows: catch (err: any) { LOG.error("Failed to get location with ID: " + args.id); LOG.error(err); throw new Error(err); ...

What is the best way to incorporate interface validation in TypeScript switch statements?

Currently utilizing Typescript and redux My goal is to compare a passed action with an interface, then execute the appropriate task export function counterReducer( state = initialState, action: CounterActionTypes ): CounterState { switch (action) { ...

Transforming JSON data into an Angular TypeScript object

Delving into the realm of Angular on my own has been quite an enlightening journey, but I'm currently facing a specific issue: My aim is to create a website using both Spring for the back end and Angular 7 for the front end. However, I've encoun ...

When using `useSWR`, it will return { null, null } for a successful request

When attempting to query the Firebase real-time database using useSWR in my next.js project, I encounter a perplexing issue where both the data and error variables always return as null. import useSWR from 'swr'; const LastSales: NextPage = () = ...

Extending Error object disrupts `instanceof` validation in TypeScript

Could someone clarify why the error instanceof CustomError part of the code below returns false? class CustomError extends Error {} const error = new CustomError(); console.log(error instanceof Error); // true console.log(error instanceof CustomError); ...

Tips for quietly printing a PDF document in reactjs?

const pdfURL = "anotherurl.com/document.pdf"; const handleDirectPrint = (e: React.FormEvent) => { e.preventDefault(); const newWin: Window | null = window.open(pdfURL); if (newWin) { newWin.onload = () => ...

Angular Error: Property 'map' is not found in type 'OperatorFunction'

Code: Using map and switchMap from 'rxjs/operators'. import { map, switchMap } from 'rxjs/operators'; Here is the canActivate code for route guard: canActivate(): Observable<boolean> { return this.auth.userObservable ...

Variable Scope is not defined in the TypeScript controller class of an AngularJS directive

I have implemented a custom directive to wrap ag grid like so: function MyDirective(): ng.IDirective { var directive = <ng.IDirective>{ restrict: "E", template: '<div style="width: 100%; height: 400px;" ag-grid="vm.agGrid ...

How can Firebase and Ionic be used to customize the password reset template for sending verification emails and more?

I'm facing an issue with firebase's auth templates not supporting my native language. Is there a way to customize the password reset template to also handle verification and email address change emails? ...

Validate that the input is an array

Looking for a way to determine if a function parameter is an array or not, and then process it accordingly. If the parameter is not an array, convert it into an array before performing the desired function. For example: interface employee { first: st ...

What is the process of invoking a service from a controller?

In my MovieSearchCtrl controller class, I have a method called returnMovies(query) that looks like this: returnMovies(query): any { return MovieSeat.MovieSearchService.getMovies(query); } Within the MovieSearchService service class, there is a functi ...

Creating conditional keys using the Zod library based on the value of another key

Incorporating the TMDB API into my project, I am making an effort to enhance type safety by reinforcing some of the TypeScript concepts I am learning. To achieve this, I am utilizing Zod to define the structure of the data returned by the API. Upon invest ...

Managing business logic in an observable callback in Angular with TypeScript - what's the best approach?

Attempting to fetch data and perform a task upon success using an Angular HttpClient call has led me to the following scenario: return this.http.post('api/my-route', model).subscribe( data => ( this.data = data; ...

Unexpected directory structure for internal npm module

Here is the package.json I use for building and pushing to an internal package registry: { "name": "@internal/my-project", "version": "0.0.0", "description": "Test package", "type&quo ...

Problem with rendering React Router v4 ConnectedRouter on nested routes

The routes for the first level are correctly displayed from Layout.tsx, but when clicked on ResourcesUI.tsx, the content is not rendered as expected (see code below). The ResourceUI component consists of 2 sections. The left section contains links, and th ...

What are some ways to expand the width of a MaterialUI form control if no value has been chosen?

I am currently working on a project where I need a dropdown menu component with specific selections. However, the layout appears to be cramped and I'm struggling to adjust the width. Additionally, I've been unsuccessful in changing the font size ...