The error message indicates that the property 'toLowerCase' is not found on type 'NonNullable<T[keyof T]>'

I've created a method called filterByFront

export const filterByFront = <T>(
  value: string,
  jsonData: T[],
  setData: (data: T[]) => void,
  filterKey: keyof T
) => {
  const originData = jsonData;
  if (!!value && !!value.trim()) {
    setData(originData);
  } else {
    const filterData = originData.filter((item) => {
      const newFilterValue = item[filterKey];
      return newFilterValue
        ?.toLowerCase()    //error message shows in this line 
        ?.includes(value.trim().toLowerCase());
    });

    setData(filterData);
  }
};

and I'm using it in components like this

<Input.Search
            key="filter_role"
            placeholder={t('common.filter')}
            onSearch={(value) =>
              filterByFront<IRoleListItem>(value, jsonData, setRoleData, 'id')
            }
          />,

the type definition

export interface IRoleListItem {
  authority?: string;

  id?: string;

  privilege?: string;

  prohibit?: string;

  tag_list?: string;
}

I encountered an error :

Property 'toLowerCase' does not exist on type 'NonNullable<T[keyof T]>'.ts(2339)

How can I resolve this error?

Answer №1

Please adhere to the following restriction when using this code snippet:

T extends Record<PropertyKey, { toLowerCase: () => string }>
:

export const filterByFront = <T extends Record<PropertyKey, { toLowerCase: () => string }>>(
  value: string,
  jsonData: T[],
  filterKey: keyof T
) => {
  const originData = jsonData;
  if (!!value && !!value.trim()) {
    console.log(originData);
  } else {
    const filterData = originData.filter((item) => {
      const newFilterValue = item[filterKey];
      return newFilterValue
        ?.toLowerCase()
        ?.includes(value.trim().toLowerCase());
    });

    console.log(filterData);
  }
};

Access Playground Link

Answer №2

The central issue at hand is that T lacks constraints, making it impossible to assume the existence of a property named toLowerCase. As mentioned by captain-yossarian in the comments below their response, types created using type automatically receive an implicit index signature, unlike types generated with interface. If you can define your role list item type using type, then their solution should suffice. Otherwise, you may need to perform a runtime check to confirm if T is indeed a string before proceeding to handle it as such:

export interface IRoleListItem {
  authority?: string;
  id?: string;
  privilege?: string;
  prohibit?: string;
  tag_list?: string;
}

export const filterByFront = <T, K extends keyof T>(
  value: string,
  jsonData: T[],
  setData: (data: T[]) => void,
  filterKey: K
) => {
  const originData = jsonData;
  if (!!value && !!value.trim()) {
    setData(originData);
  } else {
    const filterData = originData.filter((item) => {
      const newFilterValue = item[filterKey];

      if (typeof newFilterValue === "string") {
        return newFilterValue?.toLowerCase()?.includes(value.trim().toLowerCase());
      } else {
        return false;
      }
    });

    setData(filterData);
  }
};

declare const value: string;
declare const jsonData: IRoleListItem[];
declare const setRoleData: (data: IRoleListItem[]) => {};

filterByFront(value, jsonData, setRoleData, 'id');

TS 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

Is it possible to enhance an external class with a non-static method using prototypes?

Is it possible to use prototypes to add a function for a class instance? allowing me to access this or __proto__ keyword inside my method, like so: class PersonClass { name: string; constructor(name: string) { this.name = name; } sayHello() ...

What is the reasoning behind TypeScript allowing the reading of an undefined variable within a closure?

While exploring, I came across this detail that seems undocumented. Here's some legitimate TypeScript code that results in undefined being output: let x: number; const f= () => { const y= x; console.log(y); } f(); Playground Within the fu ...

Struggling to execute a basic Typescript file

I recently embarked on a journey to learn Typescript by enrolling in this specific course. The process of setting up everything seemed simple enough. I created a new directory, executed the command npm init, and followed it up with npm install --save-dev t ...

Tips for passing an array between components in Angular 2

My goal is to create a to-do list with multiple components. Initially, I have 2 components and plan to add more later. I will be sharing an array of tasks using the Tache class. Navbar Component import { Component } from '@angular/core'; impor ...

Is there an issue with the newline character ` ` not functioning properly in TypeScript when used with the `<br/>` tag?

Having trouble with using New Line '\n' ' ' in Typescript Here is an example of my typescript code: this.custPartyAddress = estimation.partyName + ',' + '\n' + estimation.partyAddress + ',' + ...

What steps should I take to modify the date format to "dd / mm / yy"?

When using 'toISOString ()' in JavaScript, it appears as shown in photo 2. How can I modify this format? Note: I am working with AngularJs. Image 1 is located in list.component.ts Additional documents: Image 1 Image 2 Image 1: formatDate(e) ...

When is the right time to develop a Node.js application using Typescript with dockerization

Currently, I am developing a full stack TypeScript application using Express for the server and React for the client. The folder structure of my project is organized as shown below: . ├──client/ <-- React app ├──server/ <-- Express serve ...

Distinguishing between type definitions for peer packages in TypeScript monorepos: a comparison of development and production

In my monorepo project, I utilize yarn workspaces and lerna, with all components written in TypeScript. Each module is housed in subfolders like packages/module-n, and every module contains its own package.json file with the following entries: "main": "di ...

Launching a Next.js/TypeScript application with an Express server on AWS Beanstalk

I successfully deployed my project on Heroku using the GitHub pipeline, but I am facing challenges when trying to do the same on AWS Beanstalk. If it's not feasible to use GitHub for deployment on Beanstalk, I am willing to upload a local file bundle ...

How can I update the (root-)Layout in NextJs 13 with the app directory following navigation?

Within my root layout structure, I have included a navigation bar that I wish to be present on every page, along with the children props for child pages/layouts: export default function RootLayout({children}: {children: React.ReactNode}) { return ( <h ...

Next.js v13 and Firebase are encountering a CORS policy error which is blocking access to the site.webmanifest file

Background: I am currently developing a website using Next.js version 13 in combination with Firebase, and I have successfully deployed it on Vercel. Upon inspecting the console, I came across two CORS policy errors specifically related to my site.webmani ...

Enhancing JSON Formatting with Angular 4 and Typescript

In the process of developing my Angular 4 application, I am interfacing with a REST API through JSON requests. As I work on creating JSON objects to send via POST requests, I find myself putting in quite a bit of manual effort to construct them... I KNOW ...

A guide on altering the color of a badge through programming

I am curious to learn how I can dynamically change the color of a badge in Angular. My goal is to initially set the color of the badge to white, and then if the percVLRiskTotal reaches a specific value, change the color to green as an example. CSS: <sp ...

Ways to incorporate suspense with NextJS 14 - how can I do it?

I am looking to add a suspense effect to the initial loading of my page while the assets are being fetched. These assets include images on the home screen or as children of the RootLayout component. How can I implement an initial Loading state for these ...

Combining actions in a chain within an NgRx effect for Angular

After successfully working on an effect, I now face the challenge of chaining it with a service called in a subsequent action after updating the state in the initial action through a reducer. Here is the effect code: @Effect() uploadSpecChange$: Observab ...

Angular: Defining variables using let and var

When working with TypeScript and JavaScript, we typically use either let or var to declare a variable. However, in Angular components, we do not use them even though Angular itself uses TypeScript. For instance, export class ProductComponent implements OnI ...

Having trouble retrieving form values in Typescript React, only receiving HTML tag as output

I am having an issue with retrieving the form value to my useRef hook as it returns the HTML tag of the form instead. To solve this, I attempted to specify the type HTMLFormElement inside the chevrons and set null as the initial value for my useRef hook. ...

Navigating json data in angular 6

I retrieved a JSON object in the following format response = [ { 'a': [ { 'b': [ { 'c': [ { 'name': 'abc', 'value': 900 ...

Is it necessary to validate a token with each change of page?

Currently facing a dilemma while working on my react-native app. Uncertain whether I should request the server to validate the token each time the page/screen changes, such as switching from 'feed' to 'profile', or only when actual requ ...

Issue with TypeORM Many-to-Many relation returning incorrect data when using the "where" clause

I'm facing an issue with my database tables - User and Race. The relationship between them is set as Many to Many , where a Race can have multiple Users associated with it. My goal is to retrieve all the Races that a particular user is a member of. Ho ...