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