Опциональные свойства в TypeScript обозначаются знаком вопроса (?) после имени свойства. Это означает, что свойство может быть либо задано, либо отсутствовать в объекте. Это удобно при описании структур, где не все поля обязательны.
Пример:
interface User { id: number; name?: string; } const u1: User = { id: 1 }; // OK const u2: User = { id: 2, name: 'Иван' }; // OK
Тонкости:
undefined, но и полностью отсутствовать в объекте.if (user.name)) не отличает undefined от отсутствия.undefined, и обращаться к методам/свойствам без проверки.Чтобы защититься:
undefined:if (user.name !== undefined) { console.log(user.name.toUpperCase()); }
console.log(user.name?.toUpperCase());
Если у объекта описан интерфейс
{ foo?: string }, всегда ли свойствоfooможет быть только строкой илиundefined? Можно ли записать в него, например, значениеnull?
Неправильный ответ:
undefined, другое нельзя."Правильный ответ:
null, TypeScript это допускает, но только если тип расширен до string | null. По умолчанию только string или undefined.interface A { foo?: string } let x: A = { foo: null }; // Ошибка!
История
В крупном проекте часть объектов приходила с сервера без некоторых опциональных полей. Программист напрямую вызывал методы у этих свойств (например, toLowerCase()), что приводило к runtime-ошибкам, если поле отсутствовало. Чтобы решить проблему, команда внедрила строгие проверки и правила линтера на доступ к опциональным полям.
История
В логических выражениях путали наличие свойства и его истинность: if (user.email) не срабатывало для пустых строк, хотя свойство было задано. Возник баг, из-за которого некоторые уведомления не отправлялись пользователям.
История
Команда решила записывать значение null в опциональное свойство, думая, что это корректно. TypeScript выдавал ошибку, и для обхода пришлось расширить тип до string | null, что потребовало пересмотра всей бизнес-логики по работе с этими объектами.