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