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

Choosing the Right Language for AngularJS 2: TypeScript, JavaScript, or Dart?

AngularJS 2 is on the horizon, and the documentation recommends three languages: Typescript, Javascript, and Dart. As someone who primarily works with Javascript EcmaScript 5, I'm curious about the strengths and weaknesses of these three options. Cu ...

Obtain references to templates in component classes

<div> <input #ipt type="text"/> </div> Can the template access variable be retrieved from the component class? For example, is it possible to retrieve it as shown below: class XComponent{ somefunction(){ //Is it possible t ...

Is there a reason why ChromeDriver is unable to launch Chrome on Windows 7?

Having trouble getting chromedriver to work properly on Windows 7 My application (c#) launches ChromeDriver: (a) driver = new ChromeDriver(); Everything runs smoothly, except when using Windows 7. Specifically in Windows 7 (64x): The chromedriver.exe ...

Create a new function and assign it to "this" using the button inside ngFor loop

I am working with a li tag that has a *ngFor directive: <li *ngFor="let items of buttons"> <button (click)="newMap(items.id, $event)"> {{ items.name }} </button> </li> The buttons array looks like this: buttons = [ {nam ...

Thoroughly verifying API responses in RTK Query with Zod schema

I am seeking to verify the API response I receive from a REST API by utilizing a Zod schema. As an illustration, I possess this user schema along with the corresponding API import { z } from 'zod'; import { createApi, fetchBaseQuery } from ' ...

Incorrect line numbers displayed in component stack trace [TypeScript + React]

Challenge I am currently working on integrating an error boundary into my client-side React application. During development, I aim to showcase the error along with a stack trace within the browser window, similar to the error overlays found in create-reac ...

Utilizing Node.JS and Typescript to correctly define database configuration using module.exports

I am currently utilizing Mongoose in my node.js application, which is written in Typescript. The Mongoose documentation provides clear instructions on how to connect to their database like this, but I prefer to have the configuration stored in a separate ...

Is it possible for a redis client to function without having a redis datastore installed?

Currently in my node web server, I am utilizing the npm module known as redis. Upon executing my code... const client = redis.createClient(); client.on("error", function (err) { console.log("Error " + err); }); client.hmset(["key", "test keys 1", "t ...

Encountered an error while trying to install @material-ui/core through npm: Received an unexpected end of JSON input

npm install @material-ui/core npm ERR! Unexpected end of JSON input while parsing near '...X1F+dSMvv9bUwJSg+lOUX' npm ERR! A complete log of this run can be found in: npm ERR! C:\Users\WR-022\AppData\Roaming\npm-cach ...

Creating dynamic routing functionality in Angular 8 allows for a more personalized and

I am struggling with setting up routing in Angular 8. Here is how I am trying to do it: 'company/:id/activity' 'company/:id/contacts' However, I am not receiving any params in the activatedRoute: this.activateRoute.params ...

Can child directives in Angular 2 harness the power of parent providers?

I am facing an issue while trying to utilize a service as a provider for general use in a Directive rather than a Component. The problem arises when the service is not being received in the child Directive, despite my expectation to use it within the direc ...

Exploring the world of Unicode in Angular

I need to search for pokemon and retrieve all Pokémon results (with the accent included) This is my array: let games = ['The Legend of Zelda', 'Pokémon', 'Chrono Trigger'] This is how I am attempting to do it: Using HTML ...

Filtering Items in a List Based on Several Criteria using C#

In my current scenario... One of the properties of my SomeObject is string Status, which I need to focus on. The Status property can have values of "Open", "Closed", or "Finished". I have a method named FilterObjects that returns a List<SomeObject>. ...

Learn how to use DataAnnotation to serialize an object to JSON, specifically formatting double properties within a ServiceStack request

When using ServiceStack, I am trying to format a request to keep the CodValue property in the #.# format. [DataContract(Name = "request1")] public class Request1 { [DataMember(Name = "codValue")] public double CodValue { get; set; } } var request1 ...

Creating dynamic and engaging videos using Angular with the ability to make multiple requests

I am facing an issue while working with videos in Angular. I am fetching the video URLs from an API to embed them in my application using the sanitazer.bypassSecurityTrustResourceUrl function provided by Angular. The videos are being displayed correctly wi ...

Using Angular 12 to seamlessly import JSON files into TypeScript

My project contains a JSON file located at src/assets/version.json with the following content: {"VERSION":"1.0.0"} I have imported this file into a TypeScript file (e.g., *.ts) as shown below: import * as VersionInfo from 'src/ass ...

Unable to verify Angular 5 identity

After authentication, the application should redirect to another page. However, despite successful authentication according to the logs, the redirection does not occur. What could be causing this issue? auth.guard.ts: import { Injectable } from &apos ...

Eliminate elements from an array using a specific key for filtering

My Array is called MainArray MainArray=[{ {First Name: "First Name"}, {Last Name: "Contact"}, {Last Name: "Contact"} ] I am trying to trim the key-value pair from this array like this: if (key == 'First Name') { del ...

What is the most effective method to ensure that the output of a cached calculation is both efficient and secure across multiple threads?

(I apologize if this question has been addressed elsewhere; it seems like a common issue, but searching for terms like "threading" and "cache" yields overwhelming results.) I have a computationally expensive task that is accessed frequently but changes in ...

What are the circumstances under which JavaScript GCP libraries return null values?

My current project involves working with GCP and Firebase using typescript. I have been utilizing the provided libraries, specifically version 8 of Firebase, and have encountered some unexpected behavior. For instance (firebase, ver. 8.10.1) import 'f ...