How can I access properties of generic types in TypeScript?

Converting the generic type to any is a valid approach (The type E could be a typescript type, class, or interface) of various entities like Product, Post, Todo, Customer, etc.:

function test<E>(o:E):string {
  return (o as any)['property']
}

Is casting to any generally the best way to handle this situation?

The complete context was requested. Here's the entire function that is being implemented:

/**
 * 
 * @param entities The entities to search
 * @param exclude Keys to exclude from each entity
 * 
 * @return E[] Array of entities with properties containing the search term.
 */
export function search<E extends WithProperty>(query:string='', entities:E[], exclude:string[]=[]) {
  const { isArray } = Array

  query = query.toLowerCase();

  let keys:string[] = []
  if (entities.length > 0) {
    keys = excludeKeys(entities[0], exclude)
  }

  return entities.filter(function (e:E) {
    return keys.some((key)=>{
      const value = (e as any)[key];
      if (isArray(value)) {
        return value.some(v => {
          return new String(v).toLowerCase().includes(query);
        });
      }
      else if (!isArray(value)) {
        return new String(value).toLowerCase().includes(query);
      }
    })
  });
}

/**
 * The method can be used to exclude keys from an instance
 * of type `E`.  
 * 
 * We can use this to exclude values when searching an object.
 * 
 * @param entity An instance of type E
 * @param eclude  The keys to exclude
 * 
 */
export function excludeKeys<E>(entity: E, exclude: string[]) {
  const keys: string[] = Object.keys(entity);
  return keys.filter((key) => {
    return exclude.indexOf(key) < 0;
  });
}


Answer №1

If you are aware that the type constraint includes a property named "property," you can define an interface specifying this property and then use a constraint indicating that E extends it. This way, you can access that property without needing to cast it.

interface WithProperty{
  property:string;
}

function test<E extends WithProperty>(o:E):string {
  return o.property;  // or o["property"] is valid access.
}

Playground

Edit: Since you have updated your example, another approach to consider is using the keyword keyof. This method does not require knowledge of specific properties. Below is the modified code snippet:

export function search<E>(query:string='', entities:E[], exclude:string[]=[]) {
  const { isArray } = Array
  type EKey = keyof E;
  query = query.toLowerCase();

  let keys : EKey[] = []
  if (entities.length > 0) {
    keys = excludeKeys<E>(entities[0], exclude)
  }

  return entities.filter(function (e:E) {
    return keys.some((key =>{
      const value = e[key];
      if (isArray(value)) {
        return value.some(v => {
          return v.toLowerCase().includes(search);
        });
      }
      else if (!isArray(value)) {
        return new String(value).toLowerCase().includes(query);
      }
    })
  });

}
 

Regarding the excludeKeys section of the code, casting is necessary due to this prolonged discussion.

export function excludeKeys<E>(entity: E, exclude: string[]) {
 const keys: string[] = Object.keys(entity);
  return <(keyof E)[]>keys.filter((key) => {
    return exclude.indexOf(key) < 0;
   });
}

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

Basic Inquiry: Unhandled TypeError - Unable to access the property 'length' of an object that is not defined

Currently, I am utilizing a straightforward JSON Ajax request to fetch some JSON data. However, every time I attempt to use the JSON object, I encounter the following error: Uncaught TypeError: Cannot read property 'length' of undefined $(do ...

Definition for the type react-navigation-v6 <Stack.Group>

I'm having trouble figuring out the proper type definition for a Stack group that includes screens (refer to TestStack.Group and the nested TestStack.Screen). The navigation stack: const TestStack = createNativeStackNavigator<TestStackParamList> ...

Guide to organizing a one-to-one object map within Angular JS ng-repeat

Is there a way to organize a one-to-one object map in angular.js using filters (or any other technique) while working within an ng-repeat loop? This is what I currently have: obj:{ a:3, c:5, d:1, g:15 } Basically, I want to achieve s ...

Using the mouseover event in three.js to interact with child meshes

My array, objMesh, contains multiple mesh objects. Each object has a children attribute, which in turn holds an array of more mesh objects (such as countries and their islands). How can I make it so that when I hover over each mesh object, its children are ...

I am encountering an issue trying to create a Docker image featuring TypeScript

I am facing an issue while trying to build a docker image using the docker build . command in my next.js app An error is being encountered Error: buildx failed with: error: failed to solve: process "/bin/sh -c yarn run build" did not complete su ...

I am having difficulty toggling text within a for loop in JavaScript

When I display a list of cards using a for loop and click on them, I want to toggle some text. The issue I'm facing is that it works fine for the top card, but when I click on the card below, it toggles the text of the first card instead. This is desp ...

Fix for fixed scrolling in the navigation bar

Having a website that receives traffic from different countries, including Portugal and other non-English speaking places, I decided to add a translation option. However, I encountered an issue with Google's translate feature which displays a banner a ...

AngularJS parent selector nearest to the element

I have successfully implemented a code to close a custom popup using jQuery, but I am looking for a solution that utilizes AngularJS instead of jQuery. Can anyone assist me in finding the equivalent of this.closest() in AngularJS? I aim to hide .popOverla ...

Refresh a webpage using JavaScript (inside a jquery ajax call)

Seeking guidance on how to reload a page using JavaScript, I have created the following function: function update(id, name) { if(/^\d+$/.test(id)) { $.ajax({ url: baseurl + "/url/action/param/" + id + "/param2/" + unescap ...

Configuring Angular routes based on service method invocation

I have my routes configured in @NgModule. I also have a service that determines which parts of the application to display based on specific conditions. I need to call this service and adjust the routes according to its output. Issue: The route configurati ...

The inclusion of Angular 2 router queryParams in the URL is not happening

I implemented an auth guard to protect certain pages of my web-app. In order to enable users to return to the page they intended to access, I tried adding queryParams to the URL during a redirect. Initially, the code below worked as expected. However, rece ...

Troubarked by problems NodeJS faces when trying to establish a connection with CosmosDB using a connection

Having trouble with my code that fails when I try to create a new instance of the CosmosClient. The option to create a CosmosClient using a connection string should be straightforward. The environment variable holds the necessary connection string in this ...

The TypeScript error reads: "An element is implicitly assigned the 'any' type because an expression of type 'any' cannot be used to index a specific type."

[Hey there!][1] Encountering this TypeScript error message: { "Element implicitly has an 'any' type because expression of type 'any' can't be used to index type '{ 0: { image: string; title: string; text: string; }; 1: { ...

Developing a Chrome browser extension tailored for parsing unique file formats

Currently, I am working on developing a compiler for a unique conditional formatting language. My aim is to enable the capability of opening files in my language directly in Chrome by simply double-clicking on them in File Explorer (I am currently using Wi ...

Creating an interface or type in Typescript with a nested object property that uses keys from the same interface

I am looking to create an interface or type that can restrict the nested object properties based on keys defined in the main interface. class MyClass implements MyInterface { prop1: string; promp2: number; nestedObj: { prop1: string; // Allowed a ...

The issue at hand is that the headers cannot be redefined once they have already been sent

Hello, I have tried numerous solutions but have not been able to resolve the "Can't set headers after they are sent" error in the following simple code. I have spent several days working on this and would greatly appreciate any input you may have. ap ...

Attention! Circular dependency has been detected during compilation with warnings

Every time I attempt to build my project, an error is thrown- WARNING in Circular dependency detected: src\app\own-filter\own.filter.module.ts -> src\app\own-filter\own.filter.component.ts -> src\app\own-f ...

Can the dropbox option be automatically updated when input is entered in another text field?

I'm working on a form with a dropdown containing category names and a text field for entering the category code. What I need is for selecting a category name from the dropdown to automatically display the corresponding category code in the text field, ...

Craft a FormType showcase using the dynamic duo of Ajax and Jquery

If you'd like to check out the code snippet for reference, please visit: This view serves as the canvas where innovation blends with execution. As I embark on this journey towards dynamic form creation, every step counts. Thank you for being part of ...

Having trouble transferring data from Flask to JavaScript as JSON when using a separate .js file

In my templates/index.html file, I have the following code: <!DOCTYPE html> <html lang="en"> <head> <meta http-equiv="content-type" content="text/html; charset=utf-8" /> <style> </style> </head> & ...