Механизм optional chaining (?.) появился в JavaScript для удобного безопасного доступа к свойствам и методам объектов, которые могут быть необязательно определены. В TypeScript он стал особенно полезен, поскольку помогает избежать ошибок времени исполнения, связанных с обращением к свойствам или методам undefined или null.
До появления optional chaining разработчикам приходилось вручную проверять существование каждого уровня вложенности объекта, что делало код длинным и неудобочитаемым:
if (obj && obj.a && obj.a.b) { // ... }
При обращении к вложенным свойствам у неопределённого объекта возможна ошибка времени исполнения: Cannot read property 'x' of undefined. Кроме того, длинные цепочки проверок затрудняют поддержку и воспринимаемость кода.
Optional chaining (?.) позволяет обращаться к вложенным свойствам, методам или элементам массива, автоматически возвращая undefined, если какая-либо часть цепочки равна null или undefined.
Пример кода:
interface User { name: string; address?: { city?: string; }; } const user: User = { name: 'Ivan' }; console.log(user.address?.city); // undefined
Ключевые особенности:
T | undefined, что учитывается компилятором TypeScript и помогает избежать ошибок.Можно ли использовать optional chaining слева от оператора присваивания? Например: user.address?.city = 'Moscow'?
Нет, optional chaining нельзя использовать в левом выражении присваивания, это вызовет ошибку компиляции. Optional chaining работает только при чтении, а не при записи.
Можно ли воспользоваться optional chaining для вызова метода, если сам объект может быть не определён? Например: user?.logInfo()?
Да, если объект до точки вызова метода может быть undefined/null, то вызов user?.logInfo() не выбросит ошибку и просто вернёт undefined, если user не определён.
user?.logInfo(); // если user определён, вызовется logInfo, иначе ничего не произойдёт
В чём различие между optional chaining и оператором '&&' в старом стиле, например: user && user.address && user.address.city?
Optional chaining короче, работает для всех типов (включая методы и массивы), а также TypeScript учитывает его при типовой проверке. Важно, что при использовании оператора '&&' вы можете нечаянно получить не true/false или undefined, а вложенное значение. Optional chaining же гарантированно даёт либо ожидаемый тип, либо undefined, что учитывается выводом типов.
В коде используются длинные цепочки optional chaining даже там, где переменные по бизнес-логике всегда определены:
order?.customer?.address?.city = 'London';
Плюсы:
Минусы:
Используется optional chaining только при работе с внешними данными или в местах, где значения действительно могут быть неопределёнными:
const city = apiResponse?.info?.location?.city || 'Unknown';
Плюсы:
Минусы: