Angular 8 Native Typescript crash-free, accessor shorthand

时光怂恿深爱的人放手 提交于 2020-01-04 09:27:47

问题


Angular 8 :

I used to use as a short hack on typescript side :

object['accessor']['accessor']['accessor']

to get

object.accessor.accessor.accessor

without running the risk of throwing an error if one of the children was empty.

What is the best way to do this by today's ECMA Script standards inside the typescript file?

EDIT :

I found this https://medium.com/inside-rimeto/optional-chaining-in-typescript-622c3121f99b

the b/ Nested Ternary Expressions seems the best but it seems convoluted

EDIT 2 :

nevermind, this crashes the application irrecuperably (at the component level, though) just as much.

it seem newer anguar rules are more strict. they just haven't provided an alternative.


回答1:


I prefer the boolean expression approach.

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 don't care about compile time error checking you could do something weird like this. I wouldn't recommend 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"));



回答2:


there is an npm package for this named snq(Safe Navigation Query) by armanozak. Very simple and robust solution.

You can use it like this

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

And If you wonder how it is working, here is the source code I copied from github repo

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;
  }
}



回答3:


You can simply do the following

// Sample object

const object = {
    someKey: 'First Level Value',
    accessor: {
        someKey: 'Second Level Value',
        accessor: {
            someKey: 'Third Level Value',
            accessor: 'Accessor Value'
        }
    }
};

// Using ternary expression to do conditional validation check
// Usage --> condition to check ? 'Do this if condition is true' : 'Do this if condition is false'

const accessorValue = object ? // first (?) operator
    object.accessor ? // second (?) operator
        object.accessor.accessor ? // third (?) operator
            object.accessor.accessor ? // fourth (?) operator
                object.accessor.accessor.accessor :
                null : // to match the first (?) operator
            null : // to match the second (?) operator
        null : // to match the third (?) operator
    null; // to match the fourth (?) operator

console.log(accessorValue); // Accessor Value



回答4:


I like using Ramda's path function in my angular projects.

import * as R from 'ramda';

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

Another appraoch that I have been using to avoid crash if child is empty (when ramda is not around), comes from inpiration from swifts .? and ?? operators to default to something if child is empty.

You don't need fancy functions, this single liner will do the trick crash proof

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

In action:

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

// crash proof, returning: undefined
const wrongLeaf = (((wrongObject || {}).accessor || {}).accessor || {}).accessor
console.log(wrongLeaf);

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

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



回答5:


You could do something like this as a shorthand, which would allow the types to flow through, I assume.

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


来源:https://stackoverflow.com/questions/57960362/angular-8-native-typescript-crash-free-accessor-shorthand

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!