A guide on leveraging typeof within function parameters to ensure accurate variances

Let's create a simple class hierarchy and a list of instances. The goal is to filter items from the list of instances based on their class.

There are a couple of challenges:

  • We cannot use the typeof T syntax. How can this be written?
  • We cannot declare T as out variance - we don't want to instantiate anything in the method, just return instances of T. How do we convey this to TypeScript?
class A {
}

class B extends A {
}

class C extends A {
}

function filterByClass<out T extends A>(cls: typeof T, list: A[]): T[]
{
  return list.filter((item) => item instanceof T);
}

Playground Link


Edit:

The solution (by Adrian Kokot) was effective until it was realized that the example was "too simplistic". In reality, constructors have parameters, more like this:

class B extends A {
  constructor(pb: any) {
    super();
  }
}

class C extends A {
  constructor(pc: any) {
    super();
  }
}

Using modified playground provided in the answer, the issue with variance arises:

const a = new A();
const b = new B(1);
const c = new C(1);

const arrC = filterByClass(C, arr); 
Argument of type 'typeof C' is not assignable to parameter of type 'new () => C'.
  Types of construct signatures are incompatible.
    Type 'new (pc: any) => C' is not assignable to type 'new () => C'.

Answer №1

  1. You have the option to define the initial argument as a constructor, allowing you to pass the class name.

  2. To inform TypeScript that an item is an instance of the specified class, you can utilize the is operator as the return type in the filter method.

Potential resolution:

function filterByClass<T extends X>(className: new () => T, array: X[]): T[]
{
  return array.filter((item): item is T => item instanceof className);
}

filterByClass(Y, [new X(), new Y(), new Z()]); // returns Y[];

playground


Solution for update:

If you need to work with classes that have varying constructors, simply include ...args: any[] in the first parameter definition:

function filterByClass<T extends X>(className: new (...args: any[]) => T, array: X[]): T[]
{
  return array.filter((item): item is T => item instanceof className);
}

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

The error message indicates a compatibility issue between parameters 'r' and 'a'

Attempting to reproduce the code found in this blog post, but encountering some perplexing errors. import { option, identity, apply } from 'fp-ts'; import type { Kind, URIS } from 'fp-ts/HKT'; import { pipe } from 'fp-ts/lib/functi ...

Struggling to assign the data value retrieved from an API to a class variable in Angular 8

As I call the api to fetch data in the ngOnInit lifecycle hook, I am struggling with assigning the retrieved data to a class variable. Here is the relevant code snippet: tasks: Task[]; ngOnInit() { this.apiService.getTasks() .subscribe( da ...

Identifying misspelled names in shared resources textures during PIXI.js loading

Our game utilizes TypeScript, Pixi.js, VSCode, and ESLint. We maintain a dictionary of image files as follows: export function getAllImages(): {name: string, extension: string}[] { return [ {name: 'tile_lumber', extension: '.svg ...

The process of incorporating types into Node.js and TypeScript for handling req and res objects

Check out the repository for my project at https://github.com/Shahidkhan0786/kharidLoapp Within the project, the @types folder contains a file named (express.d.ts) where I have added some types in response. The (express.d.ts) file within the @types folde ...

eliminate the common elements between two arrays in typescript/javascript

I have two lists of objects, each containing two fields: let users1 = [{ name: 'barney', uuid: 'uuid3'}, { name: 'barney', uuid: 'uuid1'}, { name: 'barney', uuid: 'uuid2 ...

What is the best way to have Vue i18n fetch translations from a .json file during Unit Testing?

Previously, with vue-i18n (v8.25.0 and vue v2.6.14), I stored all translations in .ts files containing JS objects: import { LocaleMessages } from 'vue-i18n' const translations: LocaleMessages = { en: { test: 'Test', }, } expor ...

NextJS: Route Handler encountering Method Not Allowed (405) error when trying to redirect

Current NextJs version is 13.4.3 I have set up a route handler to capture POST requests. For more information on route handlers, please refer to the documentation at [https://nextjs.org/docs/app/building-your-application/routing/router-handlers] In this ...

Global Enum in Typescript that is Optimized for Inlining during Compilation

I'm facing a challenge with an enum that is widely used in my project. Having to import it into every file is becoming cumbersome. Is there a way to define the enum in the .d.ts file so that it automatically gets included when compiled to Javascript? ...

Custom JSX element failing to include children during addition

I have created a unique component in JSX, like this: const CustomComponent = ({content}) => { return <div className={content}></div>; } I am using it as follows: <CustomComponent content={"xyz"}> <p>Some additio ...

Steer clear of duplicating template literal type entries when dealing with optional routes

My code includes a type called ExtractParams that extracts parameters from a URL string: type ExtractParams<Path extends string> = Path extends `${infer Start}(${infer Rest})` ? ExtractParams<Start> & Partial<ExtractParams<Rest>& ...

Update an API call to switch from promises to observables, implementing axios

Recently, I have been experimenting with using rxjs for API requests in a React application and this is the approach that I have come up with. What are your thoughts on this method? Are there any best practices that you would recommend following? If you ...

Looking for a solution to the TypeScript & Mantine issue of DateValue not being assignable?

The required project dependencies for this task are outlined below: "dependencies": { "@mantine/core": "^7.6.2", "@mantine/dates": "^7.6.2", "@mantine/form": "^7.6.2", &q ...

Set up variables during instantiation or within the class declaration

Is there a preferred way to initialize class variables in ReactJS with TypeScript - in the constructor or when declaring the variable? Both methods seem to work equally well and result in the same transpiled javascript. export class MyClass extends Reac ...

Tips for effectively using ngOnChanges in Angular 2 to validate inputs without causing the 'Expression has changed after it was checked' error

I attempted to create my own custom component with basic validation using regex that can be passed as input to the component. There are two scenarios to consider: one where the form is initially empty (new item form) and another where data is already prese ...

The function getStaticPaths() will generate a 404 error, indicating that the page

I have encountered a persistent issue with the getStaticPaths() function throwing a 404 error. After investigating, I suspect that the problem may lie in the implementation of the getAllPostIds() function, which is supposed to generate an array of object ...

Using TypeScript to pass a callback function to labelFormatter in the legend of a Highcharts chart

I am currently experimenting with integrating HighCharts into an Angular2 project using TypeScript. My goal is to customize the appearance of the legend text, adding an image next to it. I've found that HighCharts provides a labelFormatter property w ...

Learn how to set up a class using TypeScript decorators

Is there a way to automatically initialize a class when a specific decorator is present above the class? For example: @apiController export class usersControllers extends lib.baseClasses.apiControllerBase().apiController { @lib.decorators.routesRegist ...

What is the best way to ensure that GCM push notifications are still received even when the app is closed or the

Currently, I'm in the process of developing an application using Ionic 2 that requires push notifications to be received. In certain scenarios, such as when the app is force-stopped on Android or when the device is turned off, push notifications are ...

Typescript: Securing Data with the Crypto Module

I am currently working on encrypting a password using the built-in crypto module. Previously, I used createCipher which is now deprecated. I am wondering if there is still an effective way to achieve this. Here is the old code snippet: hashPassword(pass: ...

Unexpected output from nested loop implementation

Having some arrays, I am now trying to iterate through all tab names and exclude the values present in the exclusion list. json1 ={ "sku Brand": "abc", "strngth": "ALL", "area ...