JS implement a secure retrieve function without relying on strings

When working with Lodash, one common function utilized is get, which allows for retrieval of nested properties in objects like this:

_.get(object, 'a[0].b.c');
// => 3

_.get(object, ['a', '0', 'b', 'c']);
// => 3

_.get(object, 'a.b.c', 'default');

An issue often encountered with this approach is the lack of type safety when using TypeScript, as it does not prevent potential typos. Thus, I am exploring alternative ways to achieve similar functionality without relying on strings.

const obj = {a: {b: {c: {}}}, b: {}};

const a = get(obj, obj => obj.a.b.c.d.g, 'defaultValue');


function get(obj: T, getFn, defaultValue) {
  try {
    return getFn(obj);
  } catch(err) {
    return defaultValue;
  }
}

Is this the recommended method or are there better approaches available?

Answer №1

If the object obj has a structure like this:

{a: {b: {c: { d: {} }}}, b: {}}

Your current code will not work properly and would return undefined. Make sure to include a default value in the try block as well, for example:

const obj = {a: {b: {c: { d: {} }}}, b: {}};

const a = get(obj, obj => obj.a.b.c.d.g, 'defaultValue');


function get(obj: T, getFn, defaultValue) {
  try {
    let val = getFn(obj);  
    if(val === null || val === undefined) { // CHECK THIS
      return defaultValue;
    }
    return val;
  } catch(err) {
    return defaultValue;
  }
}

Answer №2

To enhance the security of the function, it is recommended to specify the type of getFn and limit the defaultValue to match the outcome of getFn.

const obj = { a: { b: { c: { d: { g: '1' }} } }, b: {} };

function get<T, TResult>(obj: T, getFn: (o: T) => TResult, defaultValue: TResult) {
    try {
        let result =  getFn(obj);
        return result == undefined ? defaultValue : result;
    } catch (err) {
        return defaultValue;
    }
}


const aa = get(obj, obj => obj.a.b.c.d.g, 'defaultValue');
get({ x: 0 }, o => o.x, 'defaultValue'); // Compiler Error, x is number, default is string
get({ x: 0 }, o => o.x, 0); // Ok, same result  type
get({ x: { y : 1} }, o => o.x.yy, 0); // Compiler Error, Catches property typos as well

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

How can you efficiently load images as you scroll without encountering duplicates?

After researching various forums and tutorials, I have learned how to dynamically load data using AJAX calls to a database via PHP files for asynchronous loading. To display images in a random order with a limit of 12, I can use a select statement like SE ...

Troubleshooting HMR issue in webpack 4 for ReactJS: HTML and SCSS not refreshing

Currently, I am setting up webpack for my application and in development mode, I would like to enable HMR (Hot Module Replacement) that automatically refreshes the page whenever there are changes in HTML, SCSS, and JSX files. The entry point for my project ...

The issue in Angular2 viewmodel where the boolean value fails to update the *ngIf template

I'm seeking assistance with an unusual issue in my Angular2 and Typescript application. Within my template, I have the following HTML utilizing ngIf: <div *ngIf="loading" class="row"> <div class="small-3 small-centered columns" > ...

Stop a div at a specific point with this unique jQuery plugin

I am looking to implement a similar feature on my website that can be seen here: The desired functionality is when a link stops at a certain point while scrolling, and upon clicking the link it smoothly scrolls to a designated div. Additionally, as you sc ...

Module specifiers that are considered relative must always commence with either "./", "../", or just "/"

I need help with importing three.js. I have been following the documentation but I keep encountering an error message: Uncaught TypeError: Error resolving module specifier “three”. Relative module specifiers must start with “./”, “../” or “/ ...

Steps for repurposing a complete mmenu instance

Recently, I've been working with a mmenu instance and successfully adding content dynamically using ajax following the plugin's guidelines. However, my current challenge is not only to add sublevels dynamically but to completely remove all exist ...

Reducing file size through compression (gzip) on express js version 4.4.1

My express js app is functioning as a web server, but I am having trouble with serving unzipped static content (js and css files). I have tried using compression from https://github.com/expressjs/compression, but it doesn't seem to be working for me. ...

Steps for displaying a confirmation popup and redirecting to a new route using AngularJS

Is it possible to display a confirmation popup with "Yes" and "No" buttons every time there is a route change in my AngularJS App? I attempted the following approach. This event gets triggered before the route change, but despite selecting 'NO', ...

Combining and overriding two JavaScript objects in real time

I possess two objects. userprofile = { id: 1, email: hello@gmail.com, user: { id: 1, username: test, } } userprofile2 = { email: bye@gmail.com, user: { username: testtest, } } My goal is to merge userprofile with userprofile2, e ...

Only map property type when the type is a union type

My goal is to create a mapping between the keys of an object type and another object, following these rules: Each key should be from the original type If the value's type is a union type, it should have { enum: Array } If the value's type is not ...

Preventing JavaScript from refreshing the page when using location.replace for the second time with the identical URL

I've encountered an issue while using location.replace to reload a page that relies on GET variables for displaying a success message. The problem arises when the URL specified in the location.replace call is identical to the current one, causing the ...

Struggling to implement a date range picker in my NextJs Project

Can someone assist me with a design challenge I'm facing? I'm struggling to incorporate a date range picker based on the client's specifications. I am currently working on a website where I need to match the design to the mockup provided. I ...

Finding it difficult to grasp the concept of asynchronous functions in NodeJS

I've been grappling with this NodeJS challenge for a good 6 hours already. Currently, I'm working with NodeJS along with Express and MongoDB. In my database, there are two collections - Listings and Categories. Each listing is linked to a categ ...

Retrieving the $index value for the chosen option in Angular

Consider this scenario: <input ng-model="selectedColor" type="text"></input> This approach will not produce the desired outcome: <p ng-click="changeColor($index)">change color</p> Is there another way to access $index without u ...

The location.reload function keeps reloading repeatedly. It should only reload once when clicked

Is there a way to reload a specific div container without using ajax when the client requests it? I attempted to refresh the page with the following code: $('li.status-item a').click(function() { window.location.href=window.location.href; ...

Angular DatePipe is struggling to identify the date format

I am facing an issue in my Angular application where I need to display the date in the 'MM/dd/yyyy' format. The Web API is sending the date in the format of "2020-12-01T00:00:00". Even though I am using the DatePipe, it does not recogn ...

Ways to incorporate StropheJs into Angular 8

Methods I have attempted: Method 1: Downloaded the strophejs-1.3.4.zip from Unzipped the folder, strophejs-1.3.4, and placed it in the src/assets directory of my Angular 8 project. Included the following in my index.html file: <!--// Stroph ...

The Node JS API remains unresponsive when the request parameters are increased, continuing to send multiple requests to the server without receiving

Using the API below returns nothing: http://localhost:6150/api/v1/simpleSurveyData/abc/:projectId/:startDate/:endDate/:visitMonth However, if I remove any of the four parameters or provide less than four parameters, and adjust the API route in Node.js acc ...

Navigating without the need for a mouse click

Is there a way to automatically redirect without user interaction? I need the redirection to happen without clicking on anything <script> setInterval(function(){ window.location.replace("http://your.next.page/"); }, 5000); // Redirec ...

Is it necessary to enforce a check for surplus properties in the return type of a function

In this particular scenario, the TypeScript compiler does not raise an error when a function returns an object with the type UserProfile even though the expected return type is UserProfileWithNoPermissions. Here's an example: interface UserProfile { ...