Passing both the object and its attributes simultaneously for reflect-metadata in TypeScript is a feature that closely resembles functionality found

Instead of using DataAnnotation in C# to add meta attributes on properties, I am seeking a similar functionality in TypeScript for a ldap model class. The goal is to have decorators that can set the LDAP attribute used in the LDAP directory internally.

export class LdapUser {
    @ldapAttribute('sn')
    sureName: string;
}

export function ldapAttribute(attributeName: string): (target: any, propertyKey: string) => void {
    return function (target: any, propertyKey: string) {
        Reflect.defineMetadata("ldapAttribute", attributeName, target, propertyKey);
    }
}

Currently, fetching the value of the ldapAttributedecorator requires passing object and attribute names as raw strings, like so:

let user = new LdapUser();
let sureNameAttribute = Reflect.getMetadata("ldapAttribute", user, "sureName");

This approach works but may lead to runtime errors if the attribute is renamed without updating the Reflect.getMetadata() call. It also lacks intellisense support. Therefore, I am exploring a solution like this:

let sureNameAttribute = Reflect.getMetadata("ldapAttribute", user.sureName);

The challenge here is to find a way to reflectively extract the attribute name (sureName) and class object (user). While I have achieved this in C# using reflection, I need guidance on how to implement it in TS.

Workaround

Although not as seamless as using Reflection in C#, I came up with a workaround that is an improvement over plain strings:

export function getLdapAttribute<T>(instance: T, attributeName: keyof T) : string {
    let value : string = Reflect.getMetadata("ldapAttribute", instance, attributeName);
    return value;
}

Here is how you would use it:

let attributeValue = getLdapAttribute(user, "sureName");

While lacking intellisense, this workaround provides compiler error detection if the attribute name is incorrect or missing.

Answer №1

To tackle this issue, we employ the following method:

export type FieldSpec<TModel, TResult> = ((model?: TModel) => TResult) | string;

export function getFieldName<TModel, TResult>(fieldSpec: FieldSpec<TModel, TResult>): string {
    if (typeof (fieldSpec) == "string" || !fieldSpec) {
        return fieldSpec as string;
    } else {
        var fullFunc = fieldSpec.toString();
        var parts = fullFunc.split(/[.;}]/).filter(x => x.trim().length > 0);
        return parts[parts.length - 1].trim();
    }
}

By utilizing these helper functions, you can simplify your code like so:

export function getLdapAttribute<T>(instance: T, attributeName: FieldSpec<T,any>) : string {
    let value : string = Reflect.getMetadata("ldapAttribute", instance, getFieldName(attributeName));
    return value;
}

let user = new LdapUser();
let sureNameAttribute = getLdapAttribute(user, () => user.sureName);

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

Issue with Ajax Autocomplete Extender when trying to complete numbers in the input field

Here is my ASPX Code: <asp:TextBox ID="txtCollectionCode" runat="server" CssClass="txt" /> <asp:AutoCompleteExtender ID="AutoCompleteCollectionCode" runat="server" TargetControlID="txtCollectionCode" MinimumPrefixLength="1" EnableCaching="true" C ...

Rollup faces challenges when trying to bundle source code alongside Bazel and Typescript

I am attempting to create a bundle using rollup, typescript, and bazel environment. I am having trouble importing relative paths. Typescript builds correctly but rollup is unable to bundle the source. WORKSPACE # WORKSPACE workspace( name = "WORK ...

How can React TypeScript bind an array to routes effectively?

In my project, I am using the standard VisualStudio 2017 ASP.NET Core 2.0 React Template. There is a class Home included in the template: import { RouteComponentProps } from 'react-router'; export class Home extends React.Component<Rout ...

Using a ForEach iteration to loop through a table in C# and jQuery

My generated table structure is as follows: <div class="row"> <div class="col-md-12"> <div id="calendar"></div> <table id="report" class="table"> <thead> <tr> <th> ...

Step-by-step guide on incorporating an external library into Microsoft's Power BI developer tools and exporting it in PBIVIZ format

I'm attempting to create a unique visualization in PowerBI using pykcharts.js, but I'm running into issues importing my pykcharts.js file into the developer tool's console. I've tried including a CDN path like this: /// <reference p ...

Establish a table containing rows derived from an object

I am currently dealing with a challenge in creating a table that contains an array of nested objects. The array I have follows this schema: array = [ { id: 'Column1', rows: { row1: 'A', row2 ...

Exploring the Power of PrimeNG and Observables in Angular 4 with RxJS

After configuring my Angular 4 project with a service like this: const usersURL = 'http://my.super.url.php'; @Injectable() export class UserService { users: Observable<User[]> constructor (public http:Http) let tick$ = Observ ...

After utilizing the d3-scale function to declare an object, my developer visual suddenly ceases to function

Upon completing a section of a Power BI tutorial, the developer encountered a visual that displayed nothing but a blank page (despite running correctly). Unable to pinpoint the issue, debugging was initiated. The following test code snippet for debugging w ...

Angular encountered an error when trying to access the property "fruits" of an undefined object

When working with Angular, I encountered an issue where I received the error message "cannot read property 'fruits' of undefined." Within my class definition, I have included the following: export class MyClass implements OnInit { fruits: any[] ...

Is there a way to display tiff files in Google Chrome?

I've been struggling with this problem for over 48 hours now, tirelessly searching for a solution. The issue lies within an application built using the ext.net framework on the front end. Specifically, I'm encountering difficulties when it comes ...

Using a single Material Autocomplete input to handle two values within Angular

Looking to implement a search feature using Material's autocomplete that can filter by either user name or user ID. The current implementation is partially functional in this Stackblitz. When selecting a user name from the autocomplete options with a ...

How to access the final element in a JSON document stored in a Blob Storage system

If I need to access the last element of a json file for an Azure blob aggregation test, one option is to download[toStream] the entire file and validate the last element. However, I am curious if there is a more efficient method to achieve this without d ...

Typescript support on Emacs

"Is there a way to enable Typescript syntax highlighting in Emacs?" I have been struggling with this for quite some time. Using Emacs 24 on an Ubuntu Virtualbox VM, I can't seem to get package-refresh-contents to work as it just hangs on "Contacting ...

Is it necessary to include @types/ before each dependency in react native?

I am interested in converting my current react native application to use typescript. The instructions mention uninstalling existing dependencies and adding new ones, like so: yarn add --dev @types/jest @types/react @types/react-native @types/react-test- ...

Struggling with testing the checkbox when it changes inside the CardHeader Avatar={} component

I've recently implemented a feature similar to the example showcased on MaterialUI's TransferList. However, I'm encountering difficulties accessing a checkbox within the avatar={}. The project utilizes Jest and Enzyme for testing purposes. T ...

Is it possible to pass a prop from a parent container to children without knowing their identities?

I am currently working on a collapsible container component that can be reused for different sections of a form to display fields or a summary. Each container would include a Form object passed as a child. Here is the basic structure of my code: function C ...

The option value in mat-autocomplete is not displaying correctly on IOS devices

When I click on the first option in the dropdown menu, it does not display the selected option in the field. However, when I select the second option, then the value of the first option appears, and when I choose the third option, the value of the second o ...

Organized modules within an NPM package

I am looking to develop an NPM package that organizes imports into modules for better organization. Currently, when I integrate my NPM package into other projects, the import statement looks like this: import { myFunction1, myFunction2 } from 'my-pac ...

Component in Next.js fetching data from an external API

I am attempting to generate cards dynamically with content fetched from an API. Unfortunately, I have been unsuccessful in finding a method that works during website rendering. My goal is to pass the "packages" as properties to the component within the div ...

Strategies for Implementing Pagination in an Angular 2 HTML Table Without the Use of Third-Party Tools

I have an HTML table that displays basic details along with images. I am looking to implement pagination for this table in Angular 2. Are there any alternatives to using ng2-pagination? ...