Деструктурировать из возможно неопределенного свойства объекта

Проблема

Функция updateUserProfile позволяет мне получить user, сделав запрос к базе данных с предоставленным user_id, затем использовать другой запрос к базе данных, чтобы гарантировать, что предоставленный email не принадлежит другому пользователю, и, наконец, обновить пользователя в базу данных, отправив запрос с предоставленными name и email.

Проблема заключалась в том, что при проверке наличия пользователя с предоставленным email в базе данных результатом мог быть Userобъект или undefined, в зависимости от того, нашли ли мы пользователя или нет.

Объект User содержит множество свойств (id, name, email, avatar, password. >, created_at, updated_at), но мне нужно было только свойство id сравнить с предоставленным user_id, чтобы гарантировать, что письмо не принадлежит ни одному пользователю.

Я не смог использовать деструктурирование, чтобы распаковать только id из результата или переименовать его в findEmailOwner, потому что результатом может быть User объект или undefined, поэтому я получил следующее сообщение об ошибке TypeScript: «Свойство 'id' не существует для типа 'Пользователь | неопределенный'".

TLDR: мне нужно получить id путем деструктуризации значения, которое может быть object или undefined.

function updateUserProfile ({ user_id, name, email }) {
  const user = await usersRepository.findById(user_id);
 
  if (!user) {
    throw new AppError(`The user was not found.`, 401);
  }
  const { id: findEmailOwner } = await usersRepository.findByEmail(email);
// error message: “Property ‘id’ does not exist on type ‘User | undefined’.
  if (typeof findEmailOwner !== ‘undefined’ && findEmailOwner !==  user_id) {
   throw new AppError(`This email cannot be used.`, 401);
 }
 user.name = name; 
 user.email = email;
  return usersRepository.save(user);
}

Отвечать

  • Мы можем использовать краткую оценку для предоставления по умолчанию, если user является ложным значением (undefined, null, 0, -0, 0n, ”” или NaN).

ПРИМЕЧАНИЕ 1. Я могу использовать этот подход в своем приложении, поскольку id свойство, которое я хочу получить с помощью деструктуризации, не может быть присвоено какому-либо ложному значению в моей базе данных.

ПРИМЕЧАНИЕ 2. НО, если бы я получал свойство avatar, которое может быть назначено null в базе данных, этот подход не сработал бы.

// Case 1 — id (cannot contain falsy values)
// user does not exist
 const user = undefined;
 const { id } = user || {};
 console.log(id); // undefined (what we expect)
// user exists
 const user = {
 id: ‘aaaa-aaaa-aaaa-aaaa’,
 };
 const { id } = user || {};
 console.log(id); // ‘aaaa-aaaa-aaaa-aaaa’ (what we expect)
// Result: SUCCESS
// — — — — — — — — — — — — — — — — — — — — -
// Case 2 — avatar (can contain null a falsy values)
const user = undefined;
 const { avatar } = user || {};
 console.log(avatar); // undefined (what we expect)
const user = {
 avatar: ‘photo.jpg’,
 };
 const { avatar } = user || {};
 console.log(avatar); // ‘photo.jpg’ (what we expect)
const user = {
 avatar: null,
 };
 const { avatar } = user || {};
 console.log(avatar); // undefined (not good, we needed this to be null)
// Result: FAILURE
  • Другой подход – распространить user на объект перед его деструктурированием, поскольку значения null и undefined игнорируются.

ПРИМЕЧАНИЕ 1. Я бы использовал этот подход, если бы извлекал avatar свойство, которое может быть присвоено ложному значению. (null) в базе данных, так как первый подход не сработал.

ПРИМЕЧАНИЕ 2. Этот подход менее идиоматичен, поэтому я бы не стал использовать его в тех случаях, когда работает первый подход.

ПРИМЕЧАНИЕ 3. Этот подход также работает для id.

//Case — avatar (can contain null a falsy values)
const user = undefined;
const { avatar } = { …user };
console.log(avatar); //undefined (what we expect)
const user = {
 avatar: ‘picture.jpg’,
};
const { avatar } = { …user };
console.log(avatar); // ‘picture.jpg’ (what we expect)
const user = {
 avatar: null,
};
const { avatar } = { …user };
console.log(avatar); // null (what we expect)
// Result: SUCCESS

Применение метода оценки короткого замыкания к нашему коду:

function updateUserProfile ({ user_id, name, email }) {
  const user = await usersRepository.findById(user_id);
  if (!user) {
    throw new AppError(`The user was not found.`, 401);
  }
  const { id: findEmailOwner } = (await usersRepository.findByEmail(email)) || {}; // 1st approach
  if (typeof findEmailOwner !== ‘undefined’ && findEmailOwner !== user_id) {
    throw new AppError(`This email cannot be used.`, 401);
  }
  user.name = name;
  user.email = email;
  return usersRepository.save(user);
}

TLDR

- Получение свойства (которое не может быть ложным) с деструктуризацией значения, которое может быть object или undefined — используйте оценку короткого замыкания.< br /> - Получение свойства (которое может быть ложным) с деструктурированием из значения, которое может быть object или undefined — используйте оператор распространения на значение, которое может быть объектом или неопределенным.

Дополнительные ссылки

Поддерживать связь

Свяжитесь со мной через мои социальные сети. Давайте поговорим о DDD, TDD, хороших практиках и новом фильме Чудо-женщина 1984, будь то на LinkedIn или GitHub.

Расскажите, что вы сегодня узнали.