Разработка и Конфигурация · 15 мин
Как проверить тип объекта в 1С: рабочие способы и примеры
Как проверить тип объекта в 1С: функции ТипЗначения и Тип, оператор ТипЗнч, проверка по метаданным. Примеры кода, типичные ошибки и готовые решения для разработчика.
Проверка типа объекта — одна из самых частых задач при разработке на встроенном языке 1С. Она нужна, когда процедура получает параметр, который может быть и ссылкой на документ, и строкой, и числом, и код должен вести себя по-разному в зависимости от того, что именно пришло. Без корректной проверки типа программа либо падает с ошибкой «Метод объекта не обнаружен», либо молча обрабатывает данные неправильно.
В платформе 1С:Предприятие для этого есть три основных инструмента: функция ТипЗначения(), оператор ТипЗнч() и функция Тип(), которая возвращает тип по строковому имени. Дополнительно тип ссылочного объекта можно определить через его метаданные — метод Метаданные(). Каждый способ имеет свою область применения, ограничения по производительности и тонкости синтаксиса.
Материал рассчитан на разработчиков и администраторов, которые пишут или дорабатывают код на встроенном языке 1С — в общих модулях, обработчиках событий, внешних обработках и произвольных выражениях СКД. Все примеры приведены для управляемого приложения, но большинство конструкций одинаково работают и в обычных формах.
Основные инструменты проверки типа: ТипЗнч, Тип и ТипЗначения
Оператор ТипЗнч(Значение) возвращает объект типа «Тип», описывающий тип переданного значения. Сам по себе результат малоинформативен — его нужно с чем-то сравнить. Для этого используется функция Тип("ИмяТипа"), которая создаёт описание типа по строковому имени. Классическая проверка выглядит так:
Если ТипЗнч(Параметр) = Тип("ДокументСсылка.ПоступлениеТоваровУслуг") Тогда
// обработка ссылки на документ поступления
КонецЕсли;
Имена типов строятся по понятным правилам: для примитивов — "Строка", "Число", "Дата", "Булево"; для ссылок — "СправочникСсылка.Номенклатура", "ДокументСсылка.РеализацияТоваровУслуг"; для объектов — "СправочникОбъект.Номенклатура", "ДокументОбъект.РеализацияТоваровУслуг". Также существуют типы "ТаблицаЗначений", "Массив", "Структура", "Соответствие" и другие.
Функция ТипЗначения() отличается областью применения: она доступна в языке выражений компоновки данных, в отборах динамических списков и в параметрах запросов, где оператор ТипЗнч недоступен. В обычном программном коде модуля чаще используют именно ТипЗнч, а ТипЗначения встречается в текстах запросов и настройках СКД.
Проверка типа ссылки через метаданные
Когда нужно определить, ссылкой на какой именно вид документа или справочника является значение, сравнение через ТипЗнч работает, но не всегда удобно — особенно если допустимых типов много. Альтернатива — обратиться к метаданным объекта и прочитать имя вида:
Если ТипЗнч(Ссылка) = Тип("ДокументСсылка.РеализацияТоваровУслуг") Тогда
// вариант 1: через ТипЗнч
КонецЕсли;
Если Ссылка.Метаданные().Имя = "РеализацияТоваровУслуг" Тогда
// вариант 2: через метаданные
КонецЕсли;
Метод Метаданные() есть у любой ссылки и объекта. Через него доступны не только имя, но и полное имя вида (Ссылка.Метаданные().ПолноеИмя() вернёт строку вида "Документ.РеализацияТоваровУслуг"), а также родитель — это позволяет проверить, что значение вообще является документом, не перечисляя все виды:
Если Метаданные.Документы.Содержит(Ссылка.Метаданные()) Тогда
// значение — ссылка на любой документ
КонецЕсли;
Важный нюанс: вызов Метаданные() у значения, которое не является ссылкой (например, у строки или числа), вызовет ошибку выполнения. Поэтому проверку через метаданные нужно либо ставить после проверки через ТипЗнч, либо оборачивать в попытку-исключение.
Проверка типа в запросах и СКД
В языке запросов 1С проверка типа выполняется иначе — там нет функции ТипЗнч. Используются три конструкции: оператор ССЫЛКА, функция ТИПЗНАЧЕНИЯ() и оператор ВЫРАЗИТЬ. Оператор ССЫЛКА проверяет, что поле содержит ссылку на конкретный вид объекта:
ВЫБРАТЬ
Регистр.Регистратор
ИЗ
РегистрНакопления.ТоварыНаСкладах КАК Регистр
ГДЕ
Регистр.Регистратор ССЫЛКА Документ.ПриходныйОрдерНаТовары
Функция ТИПЗНАЧЕНИЯ(Поле) возвращает тип значения поля, и её можно сравнить с литералом типа через функцию ТИП(). Это полезно для составных полей, где хранятся значения разных типов. Оператор ВЫРАЗИТЬ(Поле КАК Документ.РеализацияТоваровУслуг) не проверяет, а приводит тип: если значение другого типа, результат будет NULL, что тоже используют как косвенную проверку в связке с ЕСТЬ NULL.
В схемах компоновки данных в выражениях вычисляемых полей и отборах доступна функция ТипЗначения() с тем же синтаксисом. Это единственный способ проверить тип прямо в настройках отчёта без выноса логики в код модуля.
Проверка ссылочного типа, Неопределено и NULL
Частая ситуация: параметр может быть либо ссылкой, либо Неопределено, либо пустой ссылкой. Это три разных состояния, и проверять их нужно отдельно. Значение Неопределено проверяется простым сравнением: Если Параметр = Неопределено Тогда. Пустая ссылка проверяется методом Пустая() или функцией ЗначениеЗаполнено(), которая универсально работает и для ссылок, и для строк, и для дат.
Рекомендуемый порядок проверок в защитном коде: сначала отсечь Неопределено, затем проверить тип через ТипЗнч, затем при необходимости проверить заполненность ссылки. Нарушение порядка приводит к ошибкам: вызов Пустая() у Неопределено невозможен, а сравнение типа у пустой ссылки вернёт корректный тип, что может скрыть логическую ошибку — ссылка правильного вида, но ни на что не указывает.
Значение NULL встречается только в результатах запросов (например, при левом соединении без совпадений). В коде модуля оно проверяется через Если Значение = NULL Тогда или через функцию ЕСТЬNULL() прямо в запросе. Путать NULL и Неопределено нельзя: первое — значение из запроса, второе — отсутствие значения в коде.
- 1Проверьте параметр на Неопределено: Если Параметр = Неопределено Тогда
- 2Проверьте тип: Если ТипЗнч(Параметр) = Тип("ДокументСсылка.РеализацияТоваровУслуг") Тогда
- 3Проверьте заполненность: Если Параметр.Пустая() Тогда — или используйте ЗначениеЗаполнено()
- 4Только после всех проверок обращайтесь к реквизитам и методам объекта
- 5Убедитесь, что ветка «иначе» корректно обрабатывает неподходящий тип — не оставляйте её пустой, если это может скрыть ошибку данных
Практические сценарии: составные типы и произвольные параметры
Реквизит составного типа
Если реквизит объекта имеет составной тип (например, «Контрагент» может быть ссылкой на справочник «Контрагенты» или «Организации»), проверка через ТипЗнч — стандартное решение. Для перебора нескольких допустимых типов удобно собрать их в массив и использовать метод Найти:
ДопустимыеТипы = Новый Массив;
ДопустимыеТипы.Добавить(Тип("СправочникСсылка.Контрагенты"));
ДопустимыеТипы.Добавить(Тип("СправочникСсылка.Организации"));
Если ДопустимыеТипы.Найти(ТипЗнч(Контрагент)) <> Неопределено Тогда
// тип подходит
КонецЕсли;
Универсальная функция проверки
В общих модулях часто создают функцию-обёртку, принимающую значение и имя типа строкой. Это сокращает код и централизует логику. Учтите, что функция Тип() с несуществующим именем типа вызывает исключение, поэтому имя типа лучше передавать из доверенного источника, а не из пользовательского ввода.
Проверка в обработчиках событий формы
В обработчиках вроде ПриИзменении или ОбработкаВыбора параметр ВыбранноеЗначение может содержать значения разных типов в зависимости от источника. Проверка типа в начале обработчика — обязательный элемент, иначе доработка конфигурации (добавление нового вида документов в составной тип) сломает существующий код.
При сравнении типов учитывайте различие ссылки и объекта: ТипЗнч вернёт «ДокументСсылка.Х» для ссылки и «ДокументОбъект.Х» для объекта. Если процедура должна принимать оба варианта, проверяйте оба типа или приводите объект к ссылке через свойство Ссылка.
Ограничения и производительность
Сравнение ТипЗнч(Значение) = Тип("...") — быстрая операция, но в массовых циклах (десятки тысяч итераций) вызов Тип() на каждой итерации создаёт лишние объекты. Оптимизация проста: получите тип один раз до цикла в переменную и сравнивайте с ней. Это особенно заметно в серверных процедурах пакетной обработки данных.
Второе ограничение касается тонкого клиента и веб-клиента: часть типов, доступных на сервере (например, Запрос, ПостроительЗапроса), на клиенте отсутствует. Код проверки типа, который работает в серверном модуле, может не скомпилироваться в клиентском. Директивы компиляции #Если Сервер Тогда помогают разделить такой код.
Третий момент — расширения конфигурации. Если тип документа добавлен расширением, строковое имя типа в Тип() работает так же, но при отключении расширения функция Тип() с этим именем вызовет исключение. Код, зависящий от типов расширений, стоит защищать попыткой-исключением.
Как выбрать способ проверки
Выбор инструмента зависит от контекста выполнения кода и от того, что именно нужно проверить. Для кода модулей почти всегда подходит связка ТипЗнч + Тип; для запросов — оператор ССЫЛКА; для проверки принадлежности к классу объектов (любой документ, любой справочник) — метаданные. В таблице ниже сведены основные варианты.
| Способ | Где работает | Когда применять | Ограничение |
|---|---|---|---|
| ТипЗнч + Тип | Код модулей | Проверка на конкретный тип значения | Нужно точное строковое имя типа |
| Метаданные().Имя | Код модулей | Определение вида ссылочного объекта | Только для ссылок и объектов |
| Метаданные.Документы.Содержит() | Код модулей | Проверка «это любой документ» | Только для ссылочных типов |
| ССЫЛКА | Запросы | Фильтрация по виду объекта в запросе | Только ссылочные типы |
| ТИПЗНАЧЕНИЯ / ТипЗначения | Запросы, СКД, отборы | Проверка типа в выражениях компоновки | Медленнее ССЫЛКА в запросах |
Как выбрать действие
Проверка результата и отладка
Убедиться, что проверка типа работает правильно, можно через отладчик: поставьте точку останова на строке сравнения и посмотрите значение ТипЗнч(Параметр) в табло. Платформа покажет тип в читаемом виде, и вы сможете сверить его со строкой, передаваемой в Тип(). Несовпадение даже в одной букве (например, «РеализацияТоваров» вместо «РеализацияТоваровУслуг») делает сравнение ложным.
Быстрый способ узнать точное имя типа значения без отладчика — вывести его в сообщение: Сообщить(ТипЗнч(Значение));. В окно сообщений будет выведено строковое представление типа, которое можно скопировать в вызов Тип(). Для ссылок информативнее вывести Значение.Метаданные().ПолноеИмя().
При тестировании проверяйте все ветки: передайте в процедуру значение нужного типа, значение другого типа, Неопределено и пустую ссылку. Только такой набор гарантирует, что защитный код не пропустит проблемные данные и не отсечёт корректные.
Как проверить результат
Тип в табло совпадает со строкой в Тип() и ветка кода выполняется
Типы выглядят похоже, но сравнение ложно — проверьте точное имя вида объекта
Пустая ссылка отсекается проверкой Пустая() или ЗначениеЗаполнено()
Код пытается читать реквизиты пустой ссылки
Ветка обработки Неопределено срабатывает до проверки типа
Ошибка выполнения при передаче Неопределено
Условие ССЫЛКА фильтрует записи без ошибок запроса
Ошибка синтаксиса — в запросе использован недоступный оператор ТипЗнч
Частые вопросы
Чем отличается ТипЗнч от ТипЗначения?
ТипЗнч — оператор встроенного языка, используется в коде модулей и возвращает тип значения. ТипЗначения — функция языка выражений компоновки данных и запросов, применяется в отборах, вычисляемых полях СКД и текстах запросов. В коде модулей используйте ТипЗнч, в запросах и настройках отчётов — ТипЗначения.
Как проверить, что значение — ссылка, а не объект?
Сравните ТипЗнч(Значение) с типом вида «СправочникСсылка.Имя» — если совпало, это ссылка. Универсальный способ без привязки к виду: проверить, что полное имя метаданных начинается с «Справочник.» или «Документ.», и что значение не является объектом — у объекта тип будет «СправочникОбъект.Имя».
Почему сравнение ТипЗнч(Док) = Тип("ДокументСсылка.Реализация") возвращает Ложь, хотя документ именно такой?
Чаще всего не совпадает имя вида объекта: проверьте точное имя документа в конфигураторе, включая окончания («РеализацияТоваровУслуг», а не «Реализация»). Вторая причина — значение является объектом, а не ссылкой: тогда тип будет «ДокументОбъект.Имя». Выведите ТипЗнч(Док) через Сообщить() и сравните посимвольно.
Можно ли проверить тип значения в отборе динамического списка?
Да. В настройках отбора динамического списка для поля составного типа доступно сравнение по типу через функцию ТипЗначения() в выражении отбора, а для ссылочных полей платформа часто предлагает выбор вида объекта визуально. В коде отбор устанавливается через ЭлементыОтбора с использованием соответствующего выражения.
Как проверить тип, если имя типа заранее неизвестно?
Используйте метаданные: получите Ссылка.Метаданные().ПолноеИмя() и сравните со строкой в нужном формате, либо проверьте принадлежность к классу через Метаданные.Документы.Содержит(). Для перебора всех ссылочных типов конфигурации можно пройти циклом по коллекциям метаданных и сравнить тип с каждым.
Вызывает ли Тип("ИмяТипа") ошибку при неверном имени?
Да, функция Тип() с несуществующим именем типа вызывает исключение времени выполнения. Если имя типа формируется динамически или берётся из внешних данных, оберните вызов в Попытка/Исключение и предусмотрите ветку обработки ошибки.
Что важно запомнить
В коде модулей проверяйте тип связкой ТипЗнч(Значение) = Тип("ИмяТипа"), в запросах — оператором ССЫЛКА, в отборах СКД — функцией ТипЗначения(). Для ссылок удобно определять вид через Метаданные().Имя. Всегда проверяйте значение на Неопределено до проверки типа, а заполненность ссылки — после. Различайте типы Ссылка и Объект: это разные типы с разным набором методов.