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