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

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

Как определить тип значения в 1С 8.3

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

Встроенный язык 1С 8.3 — язык с динамической типизацией: одна и та же переменная или реквизит может хранить строку, число, ссылку на документ или массив. Поэтому в универсальных процедурах, при обмене данными и при отладке почти всегда возникает задача — программно выяснить, какой именно тип сейчас содержится в значении. Для этого платформа предоставляет несколько инструментов: функцию ТипЗначения, оператор Тип, объект ОписаниеТипов и выражение «ТипЗнч».

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

Функция ТипЗначения: базовый способ узнать тип

Функция ТипЗначения(Значение) принимает любое значение и возвращает объект типа «Тип», описывающий его. Это самый прямой способ ответить на вопрос «что лежит в переменной». Результат можно вывести в сообщение, записать в журнал регистрации или использовать в сравнениях.

Значение = 42;

Сообщить(ТипЗначения(Значение)); // Число

Значение = "Текст";

Сообщить(ТипЗначения(Значение)); // Строка

Значение = Справочники.Номенклатура.НайтиПоКоду("000000001");

Сообщить(ТипЗначения(Значение)); // СправочникСсылка.Номенклатура

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

Важный нюанс: для значения Неопределено функция вернёт тип «Неопределено», а для NULL (который встречается в результатах запросов) — тип «Null». Это разные типы, и путать их нельзя, особенно при обработке левых соединений в запросах.

Функция Тип и сравнение с эталонным типом

Функция Тип("ИмяТипа") создаёт объект «Тип» по строковому имени. Именно так обычно строится проверка: получаем тип значения и сравниваем с эталоном.

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

// работаем как со ссылкой на контрагента

КонецЕсли;

Обратите внимание на сокращение ТипЗнч — это синоним ТипЗначения, обе формы равнозначны и встречаются в типовом коде одинаково часто. Имена типов ссылок строятся по шаблону «СправочникСсылка.ИмяСправочника», «ДокументСсылка.ИмяДокумента», «ПеречислениеСсылка.ИмяПеречисления» и так далее.

Для примитивных типов используются короткие имена: «Число», «Строка», «Дата», «Булево». При этом «Дата» — единый тип и для даты, и для даты-времени; отдельного типа «Время» в платформе нет. Если нужно отличить дату без времени от даты с временем, придётся анализировать само значение, а не его тип.

Проверка типа через ОписаниеТипов и СодержитТип

Объект ОписаниеТипов описывает допустимый набор типов: например, составной реквизит «Строка или ссылка на контрагента». Метод СодержитТип(Тип) проверяет, входит ли конкретный тип в это описание. Такой подход правильнее прямого сравнения, когда значение должно соответствовать набору допустимых типов, а не одному конкретному.

Описание = Новый ОписаниеТипов("Строка,Число");

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

// значение допустимо

КонецЕсли;

Типовой приём — взять описание типов из метаданных реквизита и проверить значение перед записью. Это защищает от ошибок «Несоответствие типов» при программном заполнении объектов:

ТипРеквизита = Метаданные.Документы.РеализацияТоваровУслуг.Реквизиты.Комментарий.Тип;

Если Не ТипРеквизита.СодержитТип(ТипЗнч(НовоеЗначение)) Тогда

ВызватьИсключение "Передан значение недопустимого типа";

КонецЕсли;

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

Как определить тип ссылки и получить имя объекта метаданных

Частая практическая задача — не просто узнать, что значение является ссылкой, но и понять, на какой именно объект она указывает, включая имя вида в виде строки. Для этого ссылку пропускают через метаданные:

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

ИмяТипа = Значение.Метаданные().ПолноеИмя(); // "Справочник.Номенклатура"

КонецЕсли;

Менеджеры объектов предоставляют метод ТипВсеСсылки(), возвращающий описание всех ссылочных типов данного вида: Справочники, Документы, Перечисления, ПланыСчетов и другие. Это позволяет одним условием отличить «любую ссылку на документ» от примитивного значения, не перечисляя все виды документов.

Для универсальной проверки «это вообще ссылка?» в типовых конфигурациях используется функция вида «ЭтоСсылка», которая проверяет значение через Метаданные.НайтиПоТипу(ТипЗнч(Значение)): если по типу нашёлся объект метаданных ссылочного вида — значение является ссылкой. Самостоятельно проще всего проверять через перечисление менеджеров ссылочных типов.

Порядок действий при определении типа
  1. 1
    Получите тип значения: ТекущийТип = ТипЗнч(Значение)
  2. 2
    Если нужен конкретный тип — сравните: ТекущийТип = Тип("ДокументСсылка.РеализацияТоваровУслуг")
  3. 3
    Если допустимо несколько типов — проверьте через ОписаниеТипов.СодержитТип
  4. 4
    Для ссылок при необходимости получите имя: Значение.Метаданные().ПолноеИмя()
  5. 5
    Проверьте результат в отладчике: в табло виден и тип, и представление значения

Определение типа в запросах: ТИПЗНАЧЕНИЯ и ССЫЛКА

В языке запросов тип определяется иначе — функцией ТИПЗНАЧЕНИЯ(Поле) и оператором ССЫЛКА для сравнения. Это необходимо при работе с составными полями, например с реквизитом «Контрагент», который может хранить ссылки на разные справочники.

ВЫБРАТЬ

ВЫБОР

КОГДА Регистр.Контрагент ССЫЛКА Справочник.Контрагенты

ТОГДА "Контрагент"

КОГДА Регистр.Контрагент ССЫЛКА Справочник.ФизическиеЛица

ТОГДА "Физлицо"

ИНАЧЕ "Прочее"

КОНЕЦ КАК ВидКонтрагента

ИЗ РегистрСведений.Данные КАК Регистр

Альтернатива — сравнение ТИПЗНАЧЕНИЯ(Регистр.Контрагент) = ТИП(Справочник.Контрагенты). Вариант с «ССЫЛКА» обычно читается проще и работает быстрее, а «ТИПЗНАЧЕНИЯ» полезен, когда тип нужно вывести в результат запроса или использовать в группировке.

Помните о типичной ловушке: если составное поле содержит NULL (например, из-за левого соединения), проверка «ССЫЛКА» вернёт ложь, а ТИПЗНАЧЕНИЯ даст тип Null. Такие записи нужно явно отсекать или обрабатывать через ЕСТЬNULL, иначе логика отчёта будет неполной.

Отладка: как быстро посмотреть тип в конфигураторе

Во время отладки тип значения виден без кода. В табло (окно «Вычислить выражение») рядом со значением отображается его тип — например, «СправочникСсылка.Номенклатура». Это самый быстрый способ проверить предположение о том, что пришло в процедуру.

Если значение сложное (структура, таблица значений, массив), в табло можно раскрыть его и посмотреть типы отдельных элементов. Для таблиц значений типы колонок доступны через Таблица.Колонки.ИмяКолонки.ТипЗначения — это описание типов, которое можно сравнить с ожидаемым.

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

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

Выбор подхода и ограничения

Для простой развилки логики используйте пару ТипЗнч + Тип: это быстро и читаемо. Для валидации входных параметров универсальных процедур лучше ОписаниеТипов — она явно документирует, что процедура принимает. В запросах применяйте ССЫЛКА и ТИПЗНАЧЕНИЯ, потому что встроенный язык внутри запроса недоступен.

Ограничение, о котором стоит помнить: проверка типа не проверяет заполненность. Ссылка правильного типа может быть пустой, строка — пустой, дата — равна '00010101'. Поэтому проверку типа почти всегда дополняют проверкой через ЗначениеЗаполнено или сравнением с пустой ссылкой.

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

Сравнение способов определения типа

ТипЗнч + Тип

Быстрая проверка одного конкретного типа; не подходит для составных типов и требует точного имени

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

Проверка вхождения в набор допустимых типов; требует создать или получить описание типов

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

Единственный вариант внутри запроса; работает только со ссылочными типами для ССЫЛКА

Метаданные.НайтиПоТипу

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

Частые вопросы

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

Ничем — это два имени одной функции. ТипЗнч — краткий синоним, оба варианта встречаются в типовых конфигурациях и работают одинаково. Выбор зависит только от стиля кода.

Как проверить, что значение — число, а не строка с цифрами?

Используйте условие ТипЗнч(Значение) = Тип("Число"). Строка "123" эту проверку не пройдёт. Если нужно наоборот превратить строку в число, применяют ОписаниеТипов("Число").ПривестиЗначение(Строка) — нечисловые строки дадут 0.

Как узнать тип значения, если оно может быть Неопределено?

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

Можно ли получить имя типа строкой без метаданных?

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

Как проверить тип элемента формы или реквизита объекта?

У реквизита объекта тип берут из метаданных: Объект.Метаданные().Реквизиты.ИмяРеквизита.Тип — это ОписаниеТипов. Для элемента формы аналогично доступен путь к данным, по которому через метаданные определяется тип связанного реквизита.

Работает ли ТипЗнч с массивами и структурами?

Да, функция вернёт тип «Массив» или «Структура». Но типы элементов внутри она не покажет — массив в 1С не типизирован, поэтому тип каждого элемента проверяется отдельно в цикле.

Итог

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

Тип значения определяется функцией ТипЗнч, сравнение выполняется только с объектом «Тип», а не со строкой. Для составных типов используйте ОписаниеТипов.СодержитТип, в запросах — ССЫЛКА и ТИПЗНАЧЕНИЯ. Проверку типа всегда дополняйте проверкой заполненности и учитывайте различие NULL и Неопределено.