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