Experience the crash-free, efficient accessor shorthand in Angular 8 with Native Typescript integration

Question about Angular 8:

In the past, I used

object['accessor']['accessor']['accessor']
as a quick workaround in TypeScript to access nested properties safely without risking an error if one of the children was empty.

What is the recommended approach now according to ECMAScript standards within a TypeScript file?

EDIT : While exploring options, I came across this article on optional chaining in TypeScript: https://medium.com/inside-rimeto/optional-chaining-in-typescript-622c3121f99b

The use of nested ternary expressions seems promising, but it appears quite complex.

EDIT 2: Disregard my previous findings as it led to irrecoverable crashes at the component level. It seems that newer Angular guidelines are stricter, and they have not provided a clear alternative yet.

Answer №1

I lean towards using boolean expressions.

let object = {
  accessor: {
    accessor: {
      accessor: "test"
    }
  }
}

if (object
   && object.accessor
   && object.accessor.accessor
   && object.accessor.accessor.accessor) {
  console.log(object.accessor.accessor.accessor);
} else {
  console.log(null);
}

If you're not concerned about compile time error checking, you could implement a solution like this. However, I would advise against it.

function tryGetValue(obj, propertiesPath) {
  if (!obj) {
    return null;
  }

  if (!propertiesPath) {
    return obj;
  }

  let current = obj;
  let properties = propertiesPath.split(".");
  for (let i = 0; i < properties.length; i++) {
    if (current[properties[i]] !== undefined) {
      current = current[properties[i]];
    } else {
      current = null;
      break;
    }
  }

  if (current !== undefined) {
    return current;
  } else {
    return null;
  }
}

console.log(tryGetValue(object, "accessor.accessor.accessor"));

Answer №2

If you're looking to safely navigate through object properties in JavaScript, there is a convenient npm package called snq(Safe Navigation Query) created by armanozak. This solution is both simple and robust.

To use snq, simply follow this syntax:

snq(() => object.accessor.accessor.accessor, anyDefaultValueIfYouLike);

If you're curious about how snq actually works, here's the source code directly from the Github repository:

export default function snq<T = any>(callback: () => T, defaultValue?: T) {
  try {
    const result = callback();
    return typeof result === 'undefined' ? defaultValue : result;
  } catch (err) {
    if (err instanceof TypeError) {
      return defaultValue;
    }

    throw err;
  }
}

Answer №3

Here is a simple way to achieve the desired result:

// Example object with nested properties
const obj = {
    keyOne: 'First Level Value',
    nestedObj: {
        keyTwo: 'Second Level Value',
        deeplyNestedObj: {
            keyThree: 'Third Level Value',
            finalAccessor: 'Final Accessor Value'
        }
    }
};

// Using ternary operators for conditional validation
const finalValue = obj ? 
    obj.nestedObj ?
        obj.nestedObj.deeplyNestedObj ?
            obj.nestedObj.deeplyNestedObj.finalAccessor :
            null :
        null :
    null;
    
console.log(finalValue); // Final Accessor Value

Answer №4

I find great utility in utilizing the Ramda path function within my angular projects.

import * as R from 'ramda';

const leaf = R.path(['accessor', 'accessor', 'accessor'], object);

Another approach I have adopted to prevent crashes when a child is empty (in absence of Ramda), takes inspiration from Swift's `.?` and `??` operators for defaulting to a value if the child is empty.

No need for intricate functions, this concise line will ensure crash-proof operation

const leaf = (((object || {}).accessor || {}).accessor || {}).accessor;

See it in action:

const wrongObject = { accessor: null };
const validObject = { 
  accessor: {
    accessor: {
      accessor: 'your leaf value'
    }
  }
};

// Crash-proof result: undefined
const wrongLeaf = (((wrongObject || {}).accessor || {}).accessor || {}).accessor
console.log(wrongLeaf);

// or with fallback/default value
const defaultLeaf = (((wrongObject || {}).accessor || {}).accessor || {}).accessor || 'default 123';
console.log(defaultLeaf);

const validLeaf = (((validObject || {}).accessor || {}).accessor || {}).accessor
console.log(validLeaf);

Answer №5

One way to achieve this in a more concise manner is by using the following shorthand method, enabling the smooth flow of types.

const value = (() => {try{return object.accessor.accessor.accessor}catch(e){return yourDefault;}})();

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

Automatically generated error notifications for Express-Validator

I am looking to implement an Express API and incorporate request input validation using express-validator. Here is my current validation middleware: protected validate = async (request: Request, response: Response, next: NextFunction): Promise<void> ...

Retrieve the specified data stored within the ngValue attribute of an Angular 4 component

I am currently working on an Angular 4 project and I have a requirement to extract the value of the selected option from a dropdown menu in my component. Specifically, I am trying to retrieve the value of policyType.id, which is stored in the [ngValue] att ...

The function with the argument type '(dispatch: Dispatch<ShopDispatchTypes>) => Promise<void>' cannot be assigned to a parameter of type 'AnyAction'

Error: Argument of type '(dispatch: Dispatch<ShopDispatchTypes>) => Promise<void>' is not assignable to parameter of type 'AnyAction'. useEffect(() => { dispatch(GetShops()); }, []); I am facing an issue while tryin ...

Error: The argument 'IParams' is not compatible with the parameter type 'IParams' in Typescript with NextJS14

I encountered an error in my code while using Prisma with Next.js 14 and TypeScript. The issue arises when trying to load product details via product ID. The error is captured in the screenshot below. Failed to compile. ./app/product/[productId]/page.tsx:1 ...

Angular Material Rotate Ink Bar to Vertical Orientation

After wanting to change the orientation of Angular Material's Tab Component to vertical, I visited this page (Tabs) and experimented with the CSS. By making the necessary adjustments, I successfully displayed the tabs vertically using the following CS ...

"Angular EventEmitter fails to return specified object, resulting in undefined

As I work on a school project, I've encountered a hurdle due to my lack of experience with Angular. My left-nav component includes multiple checkbox selections, and upon a user selecting one, an API call is made to retrieve all values for a specific " ...

After a setTimeout is called, the string in Ionic/Angular 2 does not update as expected

Hey there! I've been trying to update a string linked to a specific class or tag using settimeout or another callback, but unfortunately, I haven't had any success. It seems to work perfectly fine when triggered by a button click, but for some re ...

Tips for configuring HttpHeaders in Angular 5

I need help understanding how to properly handle headers with HttpHeaders in order to use them for http requests using HttpClient. const headers = new HttpHeaders(); headers.append('foo', 'bar'); headers.set('foo', 'bar& ...

Issue with ngOnInit not triggering upon opening dialog

Upon opening the dialog, the ngOnInit function is not triggered as expected. Strangely, the only way I am able to get it to fire is by resizing the window. I attempted to use detectChanges and zone.run() but unfortunately, it did not have any effect. Belo ...

Is it possible to change the value of a react-final-form Field component using the onSelect function?

I am currently working on a React application using TypeScript and incorporating the Google Places and Geocoder APIs through various React libraries such as "react-places-autocomplete": "^7.2.1" and "react-final-form": "^6.3.0". The issue I'm facing ...

You won't find the command you seek within the confines of "tsc."

Whenever I type tsc into the terminal (regardless of location), I am met with the following message: $ npx tsc --version This is not the tsc command you are looking for In order to access the TypeScript compiler, tsc, from the command li ...

VSCode is unable to locate the typeRoots type declarations

I have organized all the type definitions that will be used in my application into a single file. I created a folder named @types and an index.d.ts file that exports every interface/type needed. I updated my tsconfig.json to include the @types folder: { ...

Using TypeScript and encountering Error TS2345 when trying to utilize Promise.all() in a dialog component

I have a TypeScript function that I need help with: private async deleteSelectedLuminaires (): Promise<any[]> { return this.dialogService.open({ viewModel: DeleteLuminaire, model: 'Cancel or Ok', lock: false }) .whenClosed((res ...

Tips for validating Angular form group input depending on the value of another input within the form?

I am facing an issue with form validation in my Angular version 8 application. I need to validate a form based on the following rules: If a file is uploaded (even if just clicking the button without selecting a file), then the Reason input is not required ...

Form validation is an essential feature of the Angular2 template-driven sub form component

I'm currently working on a template-driven form that includes a group of inputs generated through an ngFor. My goal is to separate this repeating 'sub-group' into its own child component. However, I'm encountering difficulties in ensur ...

The issue arises when TypeScript is unable to accurately infer the type as not being undefined following a type guard condition using

The following code snippet illustrates that in the else statement, it is evident that b cannot be undefined (a||b returns truthy and since a is falsy, b must be truthy). Why does Typescript show the error 'b' is possibly 'undefined', a ...

Exploring the Power of Observables in Angular 2: Chaining and

Hi there! I'm relatively new to Angular and still getting the hang of observables. While I'm pretty comfortable with promises, I'd like to dive deeper into using observables. Let me give you a quick rundown of what I've been working on ...

Value of type 'string' cannot be assigned to type '{ model: { nodes: []; links: []; }; }'

I am a beginner in TypeScript and I have added types to my project. However, I am encountering an error with one of the types related to the graph: Type 'string' is not assignable to type '{ model: { nodes: []; links: []; }; }'.ts(2322) ...

Utilize Angular 2 to search and filter information within a component by inputting a search term from another component

In my application, I have a Component named task-board which contains a table as shown below: <tr *ngFor="let task of tasks | taskFilter: searchText" > <td>{{ task.taskName }}</td> <td>{{ task.location }}</td> <td>{{ ta ...

Differences between NgRx @Effect and createEffect

Can you explain the distinction between using createEffect versus the @Effect annotation in ngrx? @Injectable() export class ContactsEffects { constructor( private actions$: Actions, private contactsService: ContactsService, private contacts ...