Поскольку JavaScript представил примитивный тип под названием symbol в ECMAScript 2015, TypeScript также поддерживает его изначально. Привилегия кодирования на этом языке со статической типизацией дает разработчикам возможность использовать типы для установления определенных границ и, таким образом, ускоряет сам процесс разработки. Сегодня я рассмотрю наиболее популярные способы использования типа symbol, которые могут улучшить рабочие процессы читателя.

Защита от десериализации атрибутов

Сериализация в JavaScript может легко стать сложной из-за сложных правил, которые управляют проверками примитивов и типов оболочки, особенно когда речь идет об операторе typeof. Проекты, которые полагаются на правильную сериализацию, обычно используют хорошо протестированную внешнюю библиотеку для выполнения этой работы. К сожалению, использование специализированной библиотеки не всегда может охватывать все важные случаи.

Я считаю, что десериализация (преобразование объекта, сохраненного на определенном носителе в представление в памяти), всегда должна удалять неучтенные - для атрибутов из входа. Если этого не произойдет, некоторые компоненты системы могут переместить вредоносный объект результата в привилегированные части рассматриваемой кодовой базы, что может привести к серьезным повреждениям, в зависимости от уязвимости. Поскольку TypeScript не имеет чисто номинальной системы типов, а имеет структурную систему, отслеживание вышеупомянутой проблемы может оказаться трудным даже для опытных разработчиков.

Например, система, которая позволяет регистрироваться внештатным пользователям. требует двух строковых аргументов username и password в теле запроса определенной конечной точки. После десериализации его контроллер передает результат в функцию, способную создавать пользователей, которые принимают объект, содержащий три аргумента: username, password и необязательное логическое значение staff. Если десериализация не удаляет дополнительные атрибуты из тела запроса, то злонамеренный агент может явно отправить аргумент staff (со значением true) для получения дополнительных прав, как показано в примере ниже:

Использование атрибута с символическим ключом служит одним из многих решений вышеупомянутой угрозы безопасности. Поскольку символы неявно работают с десериализацией, функция, на которую ранее ссылались, может ожидать специальный атрибут, определенный с использованием символа в качестве ключа, для контролируемого повышения привилегий. Чтобы проиллюстрировать изменение, я написал сниппет, доступный ниже:

Как я писал ранее, некоторые библиотеки сериализации предоставляют своим пользователям возможности для удаления неопределенных атрибутов. Моя любимая библиотека, называемая io-ts, поддерживает вышеупомянутую функцию с помощью конструктора кодеков exact. Обычно я использую его в сочетании с конструкторами readonly и type для создания объектных кодеков.

Снижение риска сериализации атрибутов

Как указывалось выше, сериализация (или, скорее, преобразование в строку JSON) пропускает символы. Этот факт позволяет определять скрытые атрибуты в объектах, не беспокоясь об их возможном раскрытии. Я подготовил простой фрагмент для демонстрации вышеупомянутой идеи в действии:

Существует несколько способов раскрытия секретной информации, а именно уже упомянутая сериализация (описанная), запись объектов в консоль (не может печатать атрибуты с символьными ключами) или перечисление ключей (как и раньше). Вышеупомянутый метод можно использовать для передачи информации о метаданных без явного удаления таких атрибутов во время маршалинга. Прежде чем применять этот шаблон, я советую читателю рассмотреть его практичность в отношении задачи как ручной - имплицитность может работать в чью-то пользу, если ее применять и управлять правильно.

Номинальное ограничение ввода

Как я уже говорил, TypeScript не ведет себя как язык с номинальной типизацией. Существуют определенные исключения (например, enums), но я считаю, что сначала следует рассматривать его как язык со структурной типизацией как наиболее разумный подход. Разработчики TypeScript могут до некоторой степени добиться номинальной типизации, как показано в примере ниже:

В приведенном выше фрагменте показано, как типы User и UserDto, даже если они имеют одни и те же атрибуты данных, используют разные символьные ключи, чтобы различать друг друга. Чтобы облегчить бремя внедрения правильных символов в соответствующие объекты от разработчиков, я создал две простые вспомогательные функции (читатель мог думать о них как о конструкторах), которые строят их, не раскрывая никакой логики на основе символов. . Поскольку TypeScript рассматривает эти две структуры как отдельные типы, я доказал, что рассматриваемый язык действительно поддерживает некоторые аспекты номинальной типизации.

Резюме

Как было показано, TypeScript заимствует тип символа из JavaScript и рассматривает его как первоклассного гражданина своей системы типов, что позволяет разработчикам использовать символы и шаблоны проектирования для создания структур, решающих их архитектурные проблемы. Конструкции на основе символов могут защитить разработчиков от импорта или экспорта потенциально вредных фрагментов информации и сделать возможным объявление номинальных типов. Если вам, дорогой читатель, известен еще один пример использования символов в повседневных ситуациях кодирования, поделитесь им в разделе комментариев к этой статье.