Obtain the precise Discriminated conditional unions type in the iterator function with Typescript

export type FILTER_META =
  | {
      type: 'string';
      key: string;
      filters: { id: string; label?: string }[];
    }
  | {
      type: 'time';
      key: string;
      filters: { min: string; max: string  }[];
    }
  | {
      type: 'range';
      key: string;
      filters: { min: number; max: number }[];
    };

 type Unpacked<T> = T extends (infer U)[] ? U : T;
 type Foo = Unpacked<FILTER_META['filters']>;

// how to determine comparer type from meta object
// comparer:Foo doesn't work
// const comparator = <T extends FILTER_META, U extends Unpacked<T['filters']>>(

const comparator = (meta: FILTER_META, item: any, comparer: any) => {
  const DATE_PREFIX = '1/1/2022 ';

  switch (meta.type) {
    case 
      return item?.[meta.key]?.toLowerCase() === comparer.id?.toLowerCase();
    case 'time': {
      const { min, max } = comparer;
      const compTime = new Date(DATE_PREFIX + item?.[meta.key]);
      return (
        new Date(DATE_PREFIX + min) <= compTime &&
        compTime <= new Date(DATE_PREFIX + max)
      );
    }
    case 'range': {
      const { min, max } = comparer;
      const compItem = item?.[meta.key];
      return min <= compItem && compItem <= max;
    }
  }
};


const genericFilter =
  (filterMeta: FILTER_META[]) =>
  (list = []) =>
    list.filter((item) =>
      filterMeta
        .filter((fMeta) => fMeta.filters.length)
        .every((meta) =>
          meta.filters.some((ft: any) => comparator(meta, item, ft))
        )
    );

This is a versatile filtering function that aims to sort an array using various filter types. It receives an assortment of different filters in an array and employs the comparer function to execute the filtering.

How can I specify the type of the third argument comparer:any based on the first argument which is of type FILTER_META

Find the code on Stackblitz via the following link: https://stackblitz.com/edit/typescript-ku6bq7

Answer №1

Ensure that the variable in switch(theValue) is identical to the one being nested into (e.g. theValue.filters.id). By utilizing switch(theValue.type), TypeScript can recognize that the filters of the current theValue are of type "string" rather than "time". In its absence, TypeScript cannot infer if id is a key in comparer since it's uncertain whether comparer is of type "string", "time", or "range". Hence, comparer.id will not be considered valid by TypeScript.

For instance, if fo is specifically defined as: (please note: .filters is not an array)

type fo =  {
  type: 'string';
  key: string;
  filters: { id: string; label?: string }; // not an array (is unpacked")
}
| {
  type: 'time';
  key: string;
  filters: { min: string; max: string }; // not an array (is "unpacked")
}
| {
  type: 'range';
  key: string;
  filters: { min: number; max: number }; // not an array (is "unpacked")
};

then this functionality applies:

const comparator = (meta: FILTER_META, item: any, comparer: fo) => {
  const DATE_PREFIX = '1/1/2022 ';

  switch (comparer.type) {
    case 'string':
      return item?.[meta.key]?.toLowerCase() === comparer.filters.id?.toLowerCase();
    case 'time': {
      const { min, max } = comparer.filters;
      const compTime = new Date(DATE_PREFIX + item?.[meta.key]);
      return (
        new Date(DATE_PREFIX + min) <= compTime &&
        compTime <= new Date(DATE_PREFIX + max)
      );
    }
    case 'range': {
      const { min, max } = comparer.filters;
      const compItem = item?.[meta.key];
      return min <= compItem && compItem <= max;
    }
  }
};

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

What is the purpose of running tsc --build without any project references?

Out of curiosity, I decided to experiment by executing tsc --build on a project without any project references. Surprisingly, the command ran smoothly and completed without any issues. I expected there to be a warning or error since the build flag is typic ...

Confirm whether the Iterator type is the same as the AsyncIterator type

Is there a clever JavaScript technique to differentiate between Iterator and AsyncIterator without initiating the iteration process? I'm attempting to create a type checker like this: function isAsyncIterator<T>(i: Iterator<T> | AsyncIter ...

Utilizing a dictionary for comparing with an API response in order to generate an array of unique objects by eliminating duplicates

I currently have a React component that utilizes a dictionary to compare against an API response for address state. The goal is to map only the states that are returned back as options in a dropdown. Below is the mapping function used to create an array o ...

Learn how to efficiently disable or enable a button in Angular depending on the selected radio button

In order to disable the button when the remarks are marked as failed. Here is an example scenario: Imagine there is an array containing two to four items. First example: ITEM 1 -> FAILED -> Remarks (required) ITEM 2 -> FAILED -> Remarks (r ...

What is the best way to import a TypeScript file in index.js?

I've recently developed an application using the react-express-starter template. I have a "server" directory where the backend is created by nodejs, containing an index.js file: const express = require('express'); const app = express(); c ...

Identifying the state type within the scope of TypeScript

For my project involving BMI calculation, I want to store the results in an array within a state and keep them locally. export type BmiContextState = { weight: number | undefined; height:number | undefined; open:boolean|undefined; alert:boo ...

What is the proper way to declare app.use using TypeScript with the node.js Express module?

I am working on a node.js app that utilizes typescript with express. In my code, I have defined an error middleware function as shown below: app.use((error:any, req:Request, res:Response, next:NextFunction) => { res.status(500).json({message:error.m ...

Tips for sending a query using the http GET method in Next.JS 14 API routes

When using the Next.js 14 API route, I am passing a page in the GET method to paginate the data fetched from my database. However, an error is thrown when trying to retrieve the query from the request: Property 'query' does not exist on type &a ...

Using Typescript to overload functions with varying first parameters

I am facing a scenario where I have a parent class that requires a method implementation with either one or two parameters depending on the child class. class MyClass { update(obj: HashMap); update(id: ID, obj: HashMap); update(objOrId: HashM ...

What is the best way to link function calls together dynamically using RXJS?

I am seeking a way to store the result of an initial request and then retrieve that stored value for subsequent requests. Currently, I am utilizing promises and chaining them to achieve this functionality. While my current solution works fine, I am interes ...

Angular 6: Dealing with Type Errors in the HttpClient Request

I am encountering issues with my services. I am attempting to retrieve a list of media files (generated by NodeJS, which generates a JSON file containing all media items). Although I can successfully fetch the data, I am facing an error stating "Property & ...

The TypeScript error is causing issues in the Express router file

Here is the structure of my module: import * as express from 'express'; let router = express.Router(); router.post('/foo', function(req,res,next){ // ... }); export = router; However, I'm encountering the following error: ...

Obtain the firebase object using Angular framework

Hey there, I've been working on retrieving a Firebase object using Angular and have successfully achieved that. However, I'm now faced with the challenge of how to navigate deeper into the data that is being returned (check out the images linked ...

The instanceof operator does not recognize the value as an instance and is returning false, even though it

Is there a method to verify the current instance being used? This is what I am logging to the console: import { OrthographicCamera } from 'three'; // Later in the file: console.log(camera instanceof OrthographicCamera, camera); and the result ...

Modifying the value upon saving in Adonis JS model

Using Adonis js I am facing an issue when trying to convert an ISO string to Datetime while saving data (the opposite of serializing DateTime fields to ISO string). I cannot find a way to do this in the model, like I would with a mutator in Laravel. Whene ...

How can we efficiently link data to custom objects (models) within a different class while fetching data from the server using the http.get() method in Angular CLI?

Currently in the process of developing an Angular-Cli application that involves multiple models with relational data tables. When fetching data from the server, I need to map this data to corresponding model objects. I've experimented with creating a ...

"Implemented a fresh pathway within the app-routing.module.ts file, but unfortunately, ngxAdmin is experiencing functionality issues

While customizing the ngx-admin template, I attempted to incorporate a new module into the app module and added its route in app-routing.module.ts. However, upon trying to open it, the module seems to be stuck at loading without any errors appearing in the ...

TypeScript generic types allow you to create reusable components that

function genericIdentity<T>(arg: T): T { return arg; } let myGenericIdentity: <U>(arg: U) => U = genericIdentity; I see that the 'genericIdentity' function is accepting an argument of a generic type. However, I am unsure about ...

In the past, my code would run smoothly without any issues, but now I am encountering a runtime error even though the code comp

Recently, I started learning TypeScript and encountered an issue while working with Classes. My code was functioning properly before but now it's displaying a runtime error. ...

The Microsoft.Azure.WebJobs.Script encountered an issue while attempting to cast an object of type 'System.String' to type 'Microsoft.AspNetCore.Http.HttpRequest' during the return process

I recently encountered an issue with my Azure Function written in JS that is triggered by the Service Bus and generates files to Blob Storage. When attempting to return an HTTP result, I received the following error message: System.Private.CoreLib: Except ...