Angular 8 Native Typescript без сбоев, сокращение доступа

Угловой 8:

Я использовал как короткий хак на стороне машинописного текста:

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

получить

object.accessor.accessor.accessor

без риска выдать ошибку, если один из дочерних элементов был пустым.

Как лучше всего это сделать по сегодняшним стандартам ECMA Script внутри машинописного файла?

РЕДАКТИРОВАТЬ :

Я нашел это https://medium.com/inside-rimeto/Optional-Chaining-in-typescript-622c3121f99b

b/Вложенные тернарные выражения кажутся лучшими, но они кажутся запутанными

РЕДАКТИРОВАТЬ 2:

неважно, это приводит к необратимому сбою приложения (хотя и на уровне компонентов) точно так же.

Кажется, новые правила ангуара более строгие. они просто не предоставили альтернативу.


person tatsu    schedule 16.09.2019    source источник
comment
В средней публикации, на которую вы ссылаетесь, перечислены почти все возможные обходные пути для этой проблемы. Что-то в этом посте неясно или вы просто ищете лучшее решение? (который не существует AFAIK)   -  person lukasgeiter    schedule 20.09.2019
comment
лучшее решение. недавние изменения в angular 8 делают даже эти предложения неудачными. Единственный успех, который я получил, был полным подробным if(object.accessor !== null && object.accessor !== undefined ) { console.log(object.accessor.accessor.accessor) } это далеко не идеально, когда вам нужно повторять для многих объектов и ключей, которые вы не можете перебирать   -  person tatsu    schedule 20.09.2019
comment
Дублирование Тест на наличие вложенного ключа объекта JavaScript   -  person Heretic Monkey    schedule 20.09.2019
comment
@HereticMonkey Я искал сокращение, но эта рекурсивная функция уже может сэкономить мне несколько строк. Я верну объект вместо true/false, мне нужно значение сразу   -  person tatsu    schedule 20.09.2019
comment
Но object['accessor']['accessor']['accessor'] будет выдавать ошибку в тех же ситуациях, что и object.accessor.accessor.accessor.   -  person mbojko    schedule 26.09.2019
comment
Я знаю. это моя точка зрения. но это нормально, @HereticMonkey связал меня с удовлетворительным рекурсивным решением. это не так сжато, как я мог бы надеяться, но это уже немного лучше, чем то, что мы обычно должны делать.   -  person tatsu    schedule 26.09.2019
comment
Достаточно ли этого сокращения? (() => {try{return object.accessor.accessor.accessor}catch(e){return default;}})(); ... необязательная цепочка не может появиться достаточно скоро :)   -  person Cody G    schedule 26.09.2019
comment
очень интересно, прямо сейчас это не работает для меня на уровне анализа кода. return default; и последний (); кажутся недопустимыми в текущем синтаксисе Typescript, вы уверены, что там нет ошибок? Если это действительно сработает, это будет ответом, который я ищу.   -  person tatsu    schedule 27.09.2019
comment
Ха, я написал. Не знал, будет ли это тот ответ, который вы искали.   -  person Cody G    schedule 27.09.2019


Ответы (5)


Я предпочитаю логические выражения.

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

Если вас не волнует проверка ошибок во время компиляции, вы можете сделать что-то странное. Я бы не рекомендовал это.

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"));
person Noremac    schedule 20.09.2019
comment
проверка объекта без условия равенства приведет к сбою, если объект не определен. Я не знаю, угловая это вещь или нет, но: if(object.accessor) = сбой if(object.accessor !== undefined && object.accessor !== null) = успех. бьет меня, почему это так, но это так. - person tatsu; 21.09.2019

для этого существует пакет npm с именем snq(Safe Navigation Query) от armanozak. Очень простое и надежное решение.

Вы можете использовать это так

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

И если вам интересно, как это работает, вот исходный код, который я скопировал из репозитория github.

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;
  }
}
person Ismail Sahin    schedule 26.09.2019

Вы можете просто сделать следующее

// 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
person Grey    schedule 20.09.2019
comment
это вызывает неопределенное исключение, когда аксессор отсутствует, а остальная часть компонента перестает загружаться. - person tatsu; 20.09.2019
comment
Он может отображать ошибку TypeScript во время компиляции, но ошибки во время выполнения быть не должно. - person Heretic Monkey; 20.09.2019
comment
нет, я говорю об ошибке времени выполнения, когда объект либо не существует, либо не имеет этого потомка. - person tatsu; 20.09.2019
comment
если аксессор не существует, он вернет undefined, что является ложным, поэтому он должен просто перейти к ложной стороне тройки. - person Heretic Monkey; 20.09.2019
comment
С помощью машинописного текста вы можете/должны написать класс интерфейса для вашего объекта/модели, чтобы обнаружить возможную ошибку времени выполнения при разработке. - person Grey; 20.09.2019
comment
это не избавление от ошибки, а просто перемещение ее в другое место - person tatsu; 24.09.2019

Мне нравится использовать функцию пути Ramda в моих угловых проектах.

import * as R from 'ramda';

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

Другой подход, который я использовал, чтобы избежать сбоя, если дочерний элемент пуст (когда ramda нет рядом), исходит от операторов swifts .? и ?? по умолчанию для чего-то, если дочерний элемент пуст.

Вам не нужны причудливые функции, этот единственный лайнер защитит от сбоев

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

person Rasmus Puls    schedule 26.09.2019

Я полагаю, вы могли бы сделать что-то подобное в качестве стенографии, что позволило бы пропускать типы.

const value = (() => {try{return object.accessor.accessor.accessor}catch(e){return yourDefault;}})();
person Cody G    schedule 27.09.2019
comment
действительно в самый последний момент. Осталось 14 минут. - person tatsu; 27.09.2019