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

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

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

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

При разработке и доработке конфигураций на платформе 1С:Предприятие 8 регулярно возникает задача — понять, какого типа значение хранится в переменной, реквизите объекта или параметре процедуры. Это нужно при обработке составных реквизитов, универсальных функциях, обмене данными и отладке, когда вместо ожидаемой ссылки приходит строка или значение Неопределено.

Платформа предоставляет несколько штатных механизмов для этого: функции ТипЗнч() и Тип(), объект ОписаниеТипов, а также операторы языка запросов для проверки типов на уровне СУБД. Каждый инструмент решает свою задачу, и неправильный выбор приводит к трудноуловимым ошибкам — например, сравнение типа со строкой вместо объекта Тип.

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

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

Типичный пример проверки в модуле:

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

Сообщить("Передана ссылка на номенклатуру");

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

Сообщить("Передана строка");

КонецЕсли;

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

Для вывода типа в сообщение или журнал регистрации объект Тип можно преобразовать в строку обычным присваиванием: Строка(ТипЗнч(Значение)) вернёт читаемое имя типа, например «ДокументСсылка.РеализацияТоваровУслуг».

Функция Тип — получение эталона для сравнения

Функция Тип("ИмяТипа") создаёт объект Тип по строковому имени. Именно её используют как правую часть сравнения с результатом ТипЗнч. Имя типа для ссылочных объектов строится по шаблону: вид объекта метаданных, точка, имя объекта — Тип("ДокументСсылка.ПриходнаяНакладная").

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

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

Различие ссылки и объекта при определении типа

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

Что проверяемТип ссылкиТип объекта
Справочник «Номенклатура»СправочникСсылка.НоменклатураСправочникОбъект.Номенклатура
Документ «РеализацияТоваровУслуг»ДокументСсылка.РеализацияТоваровУслугДокументОбъект.РеализацияТоваровУслуг
План счетов «Хозрасчетный»ПланСчетовСсылка.ХозрасчетныйПланСчетовОбъект.Хозрасчетный

Если универсальная процедура должна принимать и ссылки, и объекты, проверяйте оба варианта или нормализуйте входной параметр: у объекта есть свойство Ссылка, поэтому можно привести всё к ссылке перед дальнейшей логикой.

Определение типа реквизита через метаданные и ОписаниеТипов

Когда нужно узнать не тип конкретного значения, а типы, допустимые для реквизита объекта конфигурации, используется объект ОписаниеТипов. Его получают через метаданные:

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

Для Каждого ТекТип Из ОписаниеРеквизита.Типы() Цикл

Сообщить(Строка(ТекТип));

КонецЦикла;

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

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

Проверка типов в запросах

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

ВЫБРАТЬ

Регистр.Регистратор

ИЗ

РегистрНакопления.Взаиморасчеты КАК Регистр

ГДЕ

ТИПЗНАЧЕНИЯ(Регистр.Регистратор) = ТИП(Документ.РеализацияТоваровУслуг)

Функция ВЫРАЗИТЬ(Поле КАК Документ.РеализацияТоваровУслуг) не проверяет тип, а приводит его: значения других типов превратятся в NULL. Это позволяет обращаться к реквизитам конкретного вида документа через точку после приведения, не получая ошибки запроса.

Маршрут решения

Какой инструмент выбрать

Нужно проверить тип переменной в коде модуляИспользуйте ТипЗнч() в паре с Тип()
Нужно узнать допустимые типы реквизита объекта конфигурацииЧитайте свойство Тип через Метаданные и метод Типы()
Нужно отобрать записи по типу составного поля в выборкеПрименяйте ТИПЗНАЧЕНИЯ() в условии ГДЕ запроса
Нужно обратиться к реквизитам документа конкретного вида через составное полеИспользуйте ВЫРАЗИТЬ() в запросе

Практический сценарий: универсальная обработка параметра

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

Процедура ОбработатьЗначение(Значение) Экспорт

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

Возврат;

КонецЕсли;

ТипЗначения = ТипЗнч(Значение);

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

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

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

// ищем контрагента по наименованию

Иначе

ВызватьИсключение "Неподдерживаемый тип параметра: " + Строка(ТипЗначения);

КонецЕсли;

КонецПроцедуры

Явное исключение в ветке Иначе лучше, чем молчаливый пропуск: при сопровождении вы сразу увидите в журнале регистрации, какой тип пришёл на вход, вместо загадочного «ничего не произошло».

Как отладить тип значения в конфигураторе
  1. 1
    Поставьте точку останова на строке, где значение уже присвоено
  2. 2
    Запустите отладку и дождитесь остановки
  3. 3
    Откройте табло (Ctrl+Alt+W) и введите выражение ТипЗнч(Переменная)
  4. 4
    Добавьте выражение Строка(ТипЗнч(Переменная)), чтобы увидеть имя типа текстом
  5. 5
    Сравните полученный тип с ожидаемым и скорректируйте проверку в коде

Типичные ошибки и ограничения

Первая распространённая ошибка — сравнение результата ТипЗнч со строкой: Если ТипЗнч(Х) = "Строка" Тогда. Такое условие никогда не выполнится, потому что слева объект Тип, а справа строка. Правильно — ТипЗнч(Х) = Тип("Строка").

Вторая ошибка — попытка определить «тип значения» у несуществующего реквизита через обращение к свойству объекта. Если реквизита нет в метаданных, обращение вызовет исключение ещё до проверки типа. Для безопасной работы сначала проверяйте наличие реквизита через метаданные или используйте структуру с проверкой наличия ключа.

Третий момент — составные типы и NULL из запросов. Если поле запроса имеет составной тип, а в конкретной записи хранится значение другого вида, результатом будет NULL, а ТипЗнч вернёт тип «Null», который нужно обрабатывать отдельно от Неопределено.

Типичные ошибки
01
Сравнение ТипЗнч() со строкой вместо Тип() — условие всегда ложно
02
Путаница между ДокументСсылка и ДокументОбъект — нужная ветка кода не выполняется
03
Игнорирование различия Null и Неопределено — ложные срабатывания проверок
04
Обращение к имени типа, которого нет в конфигурации, без попытки-исключения — падение кода при переименовании объекта

Ещё одно ограничение: ТипЗнч не скажет ничего о «прикладном смысле» значения. Для перечислений типом будет ПеречислениеСсылка.ИмяПеречисления, а проверку конкретного значения нужно делать отдельным сравнением.

Итог

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

В модуле тип определяют через ТипЗнч() и сравнивают с Тип(); допустимые типы реквизита читают через Метаданные и ОписаниеТипов; в запросах используют ТИПЗНАЧЕНИЯ() и ВЫРАЗИТЬ(). Всегда различайте ссылку и объект, а также Null и Неопределено.

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

Как вывести имя типа значения в сообщение пользователю?

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

Чем отличается Неопределено от Null при проверке типа?

Неопределено — значение по умолчанию для незаполненных переменных и реквизитов, а Null приходит из запросов, когда поле составного типа содержит значение другого вида. ТипЗнч вернёт для них разные типы, и проверять нужно оба, если данные смешанного происхождения.

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

Используйте метод Справочники.ТипВсеСсылки() или аналогичный для других менеджеров: получите описание типов всех ссылок и вызовите СодержитТип(ТипЗнч(Значение)). Альтернатива — проверка через XMLТипЗнч или анализ имени типа строкой, но первый способ надёжнее.

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

Да, функции ТипЗнч и Тип доступны на клиенте, включая тонкий и веб-клиент. Ограничение касается только типов, недоступных на клиенте по своей природе, — например, объектов данных, которые существуют только на сервере.

Как задать тип для новой колонки таблицы значений?

Передайте в метод Добавить() коллекции колонок описание типов: ТЗ.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура")). Без указания типа колонка будет иметь произвольный тип, что ухудшает производительность и мешает контролю данных.

Почему сравнение ТипЗнч(Х) = Тип("Строка") не срабатывает для строки из запроса?

Скорее всего, в поле запроса хранится не строка, а NULL, или поле имеет составной тип и значение пришло другого вида. Проверьте результат запроса в консоли: выведите ТипЗнч для каждой строки выборки и убедитесь, что тип именно «Строка», а не Null.