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