К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как сравнить типы в 1С: практическое руководство

Практическое руководство по сравнению типов в 1С: функции Тип() и ТипЗнч(), проверка ссылочных и примитивных типов, типичные ошибки и примеры кода для разработчика.

Сравнение типов — одна из базовых операций во встроенном языке 1С, которая встречается при обработке произвольных значений, написании универсальных процедур и проверке параметров перед выполнением логики. Ошибка в определении типа приводит к падению кода с сообщением вида «Преобразование значения к типу не может быть выполнено», поэтому проверка типа перед операцией — стандартный приём защитного программирования.

В 1С тип значения не сравнивается напрямую оператором «=» как обычное значение. Для работы с типами предусмотрены специальные функции Тип() и ТипЗнч(), а результат сравнения — это булево значение, которое используется в условиях. Понимание того, как именно платформа представляет типы, избавляет от трудноуловимых ошибок, например когда сравнение «вроде бы верное», но всегда возвращает Ложь.

Материал рассчитан на разработчиков и внедренцев, которые работают с кодом в модулях объектов, общих модулях и внешних обработках. Разобраны сравнение примитивных и ссылочных типов, проверка составных типов, работа с описанием типов и типичные ловушки, включая сравнение строкового имени типа с объектом типа.

Как устроены типы во встроенном языке 1С

Во встроенном языке тип — это отдельное значение особого вида «Тип». Его нельзя создать произвольно: объект типа получают либо функцией Тип("ИмяТипа"), либо функцией ТипЗнч(Значение), которая возвращает тип уже существующего значения. Оба результата можно сравнивать между собой оператором равенства.

Типы делятся на примитивные (Число, Строка, Дата, Булево, Неопределено, Null) и прикладные, определяемые конфигурацией: ссылки на справочники, документы, перечисления, планы счетов и так далее. Для прикладных типов имя строится по шаблону: вид объекта, точка, имя объекта метаданных — например, ДокументСсылка.РеализацияТоваровУслуг.

Важно понимать, что Тип("Строка") и строка "Строка" — разные вещи. Первое — объект типа, второе — обычный текст. Сравнение ТипЗнч(Значение) = "Строка" всегда вернёт Ложь, даже если значение действительно строковое. Это самая частая ошибка начинающих разработчиков.

Базовое сравнение: ТипЗнч() и Тип()

Стандартная конструкция проверки выглядит так: слева — тип фактического значения, справа — ожидаемый тип, полученный по имени. Результат подставляется в условный оператор.

Если ТипЗнч(Параметр) = Тип("Число") Тогда

// работаем как с числом

ИначеЕсли ТипЗнч(Параметр) = Тип("Строка") Тогда

// работаем как со строкой

КонецЕсли;

Для ссылочных типов указывается полное имя с видом объекта:

Если ТипЗнч(Контрагент) = Тип("СправочникСсылка.Контрагенты") Тогда

// это ссылка на справочник «Контрагенты»

КонецЕсли;

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

Проверка ссылочных типов и значений Неопределено

Особый случай — значения Неопределено и Null. У них нет прикладного типа, и попытка обратиться к свойствам такого значения вызовет ошибку. Перед сравнением типов полезно отсечь эти варианты явно:

Если Значение = Неопределено Тогда

Возврат;

КонецЕсли;

Для проверки, является ли значение ссылкой вообще (любого вида), удобно сравнение через перечень имен или через метаданные. Универсальный приём — получить метаданные значения и проверить их принадлежность к классу:

МетаданныеЗначения = Значение.Метаданные();

Если Метаданные.Справочники.Содержит(МетаданныеЗначения) Тогда

// это ссылка на какой-то справочник

КонецЕсли;

Такой подход работает только для ссылочных значений: у примитивных типов метода Метаданные() нет, и вызов приведёт к ошибке. Поэтому сначала проверяют примитивные типы через ТипЗнч(), а работу с метаданными выполняют уже внутри ветки, где значение гарантированно ссылочное.

Порядок безопасной проверки типа
  1. 1
    Отсеките Неопределено и Null явным сравнением
  2. 2
    Проверьте примитивные типы через ТипЗнч() = Тип("...")
  3. 3
    Для ссылочных типов сравните с Тип("ВидОбъекта.ИмяОбъекта")
  4. 4
    При необходимости уточните вид через Значение.Метаданные()
  5. 5
    Только после проверки обращайтесь к реквизитам значения

Составные типы и описание типов

Реквизиты объектов и параметры могут иметь составной тип: например, поле «Контрагент» допускает ссылку на справочник «Контрагенты» и на справочник «Организации». В этом случае одного сравнения недостаточно — нужно проверить принадлежность типа значения списку допустимых типов.

Для этого служит объект ОписаниеТипов. Его метод СодержитТип() возвращает Истина, если переданный тип входит в описание:

Описание = Новый ОписаниеТипов("СправочникСсылка.Контрагенты,СправочникСсылка.Организации");

Если Описание.СодержитТип(ТипЗнч(Значение)) Тогда

// тип допустим

КонецЕсли;

Описание типов реквизита можно получить из метаданных: Метаданные.Документы.РеализацияТоваровУслуг.Реквизиты.Контрагент.Тип. Это правильный способ проверки «подходит ли значение под тип реквизита» без перечисления допустимых типов вручную — при изменении конфигурации код не придётся переписывать.

Сравнение типов в запросах

В языке запросов 1С сравнение типов выполняется иначе — функций ТипЗнч там нет. Используются оператор ССЫЛКА для уточнения вида ссылки и функция ТИПЗНАЧЕНИЯ() для получения типа поля:

ВЫБРАТЬ

Реализация.Контрагент

ИЗ

Документ.РеализацияТоваровУслуг КАК Реализация

ГДЕ

Реализация.Контрагент ССЫЛКА Справочник.Контрагенты

Оператор ВЫРАЗИТЬ(Поле КАК Справочник.Контрагенты) не только проверяет, но и приводит значение к указанному типу: если фактический тип не совпадает, результатом будет NULL. Это используют для безопасного обращения к реквизитам составных полей через точку — без приведения запрос вернёт ошибку или пустые значения.

Для примитивных типов в запросе применяют функцию ТИПЗНАЧЕНИЯ(Поле) = ТИП(ЧИСЛО) и аналогичные конструкции. Учтите, что сравнение типов в запросе работает на уровне СУБД и доступно только для полей, а не для произвольных выражений встроенного языка.

Способы проверки типа

ТипЗнч() = Тип()

Универсальный способ во встроенном языке. Подходит для точного сравнения одного типа, но требует перечисления вариантов при составных типах.

ОписаниеТипов.СодержитТип()

Проверка вхождения в список допустимых типов. Удобна для составных реквизитов, но не учитывает квалификаторы длины и точности.

ССЫЛКА и ТИПЗНАЧЕНИЯ() в запросе

Единственный вариант внутри запроса. Работает на уровне СУБД, не применим к переменным встроенного языка.

Метаданные значения

Позволяет определить класс объекта (справочник, документ) и получить описание типа реквизита. Требует, чтобы значение было ссылочным.

Типичные ошибки и как их избежать

Первая группа ошибок — сравнение несравнимого. Сравнение типа со строкой, сравнение типов через операторы «больше/меньше» и попытка вывести тип в сообщение без преобразования — всё это источники сбоев. Для вывода типа в диагностическое сообщение используйте Строка(ТипЗнч(Значение)).

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

Третья группа — путаница между объектом и ссылкой. Типы СправочникСсылка.Контрагенты и СправочникОбъект.Контрагенты — разные типы. Если метод получает объект (например, в обработчике ПередЗаписью), сравнение с типом ссылки вернёт Ложь. Внутри обработчиков объектов проверяйте тип соответственно контексту или используйте ЭтотОбъект.Ссылка для сравнения по ссылочному типу.

Типичные ошибки
01
Сравнение ТипЗнч(Значение) со строкой "Число" вместо Тип("Число") — условие никогда не выполняется
02
Перепутаны СправочникСсылка и СправочникОбъект — проверка не срабатывает в обработчиках объекта
03
Имя типа собрано из внешних данных без проверки — исключение Тип() останавливает выполнение
04
Обращение к Метаданные() у примитивного значения — ошибка «Метод не обнаружен»
05
Ожидание, что СодержитТип() проверит длину строки или точность числа — квалификаторы игнорируются

Проверка результата и отладка

При отладке сравнения типов полезно вывести фактический тип значения в сообщение: Сообщить(Строка(ТипЗнч(Значение))). Для ссылочных типов вывод будет вида «СправочникСсылка.Контрагенты» — именно в таком формате имя указывается в функции Тип(), что позволяет скопировать его напрямую в код.

В конфигураторе тип текущего значения виден в табло при остановке по точке останова: выделите переменную, нажмите Shift+F9 — в окне вычисления выражения отображается и значение, и его тип. Это быстрее, чем добавлять временные вызовы Сообщить().

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

Контрольные точки

Как проверить корректность сравнения

Срабатывание условия на нужном типе
Норма

Ветка выполняется только для ожидаемого типа

Тревожный признак

Ветка выполняется всегда или никогда — ошибка в конструкции сравнения

Формат имени типа
Норма

Сообщить(Строка(ТипЗнч(Значение))) совпадает с именем в Тип()

Тревожный признак

Имена отличаются регистром или видом (Ссылка/Объект)

Поведение на Неопределено
Норма

Значение отсечено отдельной проверкой до сравнения типов

Тревожный признак

Код падает при обращении к свойствам Неопределено

FAQ

Чем отличается Тип() от ТипЗнч()?

Тип("ИмяТипа") создаёт объект типа по строковому имени, а ТипЗнч(Значение) возвращает тип уже существующего значения. В сравнении они обычно используются в паре: слева ТипЗнч фактического значения, справа Тип ожидаемого типа.

Как проверить, что значение — любая ссылка, без перечисления видов?

Точного встроенного оператора «это ссылка» нет. Практический способ — попытаться получить метаданные значения внутри Попытка/Исключение или проверить, что тип не входит в список примитивных. В запросах используют конструкцию, где поле сравнивают с NULL после приведения ВЫРАЗИТЬ.

Почему сравнение ТипЗнч(Значение) = Тип("СправочникСсылка.Контрагенты") возвращает Ложь, хотя значение — контрагент?

Чаще всего в переменной находится объект (СправочникОбъект), а не ссылка — это разные типы. Также проверьте точное имя справочника в конфигураторе: если объект метаданных называется иначе, функция Тип() либо вызовет исключение, либо сравнение не совпадёт.

Можно ли сравнивать типы оператором «<>»?

Да, неравенство типов работает так же, как равенство: ТипЗнч(Значение) <> Тип("Строка") вернёт Истина для любого нестрокового значения. Операторы «больше» и «меньше» для типов не применяются — порядок типов не определён.

Как проверить тип значения, хранящегося в реквизите составного типа, в запросе?

Используйте функцию ТИПЗНАЧЕНИЯ(Поле) в сочетании с ТИП(Справочник.ИмяСправочника) в условии ГДЕ, либо оператор ССЫЛКА. Для доступа к реквизитам конкретного вида предварительно приведите поле через ВЫРАЗИТЬ — иначе обращение через точку даст пустой результат или ошибку.

Что вернёт ТипЗнч() для Неопределено и Null?

Для Неопределено функция вернёт тип «Неопределено», для Null — тип «Null». Это легитимные типы, их можно сравнивать через Тип("Неопределено") и Тип("Null"), но практичнее отсекать такие значения прямым сравнением Значение = Неопределено до любых других проверок.

Итог

Что важно запомнить

Типы в 1С сравнивают парой ТипЗнч(Значение) = Тип("ИмяТипа"), а не со строкой имени. Для составных типов используют ОписаниеТипов.СодержитТип(), в запросах — ССЫЛКА и ТИПЗНАЧЕНИЯ(). Перед проверкой отсекайте Неопределено и помните о различии типов Ссылка и Объект.