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

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

Как получить тип реквизита в 1С 8

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

Получить тип реквизита в 1С 8 можно двумя принципиально разными способами: определить тип конкретного значения, которое сейчас хранится в реквизите, или узнать тип, заданный реквизиту в метаданных конфигурации. Первый вариант отвечает на вопрос «что сейчас лежит в переменной», второй — «какие значения вообще допустимы для этого поля». Путаница между этими задачами — самая частая причина ошибок у начинающих разработчиков.

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

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

Различие между типом значения и типом реквизита метаданных

Встроенный язык 1С разделяет два понятия. Тип значения — это тип конкретного объекта, созданного в памяти: строка, число, ссылка на справочник, дата. Функция ТипЗнч() работает именно с фактическим содержимым переменной в момент вызова.

Тип реквизита в метаданных — это декларация, хранящаяся в конфигурации. Она описывает ограничение: какие значения разрешено помещать в реквизит. Для составного типа (например, реквизит может хранить и строку, и ссылку) тип метаданных содержит несколько допустимых типов, тогда как конкретное значение всегда имеет ровно один тип.

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

Получение типа значения через ТипЗнч и Тип

Функция ТипЗнч(Значение) возвращает объект типа Тип, описывающий тип переданного значения. Чтобы сравнить полученный тип с ожидаемым, используется функция Тип("ИмяТипа"), которая создаёт описание типа по его строковому имени.

bsl
ТипЗначения = ТипЗнч(Документ.Контрагент);
Если ТипЗначения = Тип("СправочникСсылка.Контрагенты") Тогда
	Сообщить("Это ссылка на справочник Контрагенты");
ИначеЕсли ТипЗначения = Тип("Строка") Тогда
	Сообщить("Это строка");
КонецЕсли;

Имена типов для примитивов: Строка, Число, Дата, Булево. Для ссылочных типов имя строится по шаблону СправочникСсылка.ИмяСправочника, ДокументСсылка.ИмяДокумента, ПеречислениеСсылка.ИмяПеречисления, ПланСчетовСсылка.ИмяПланаСчетов и так далее.

Если нужно получить имя типа в виде строки (например, для записи в журнал или формирования имени типа динамически), используется функция XMLТипЗнч(Значение) либо обращение к метаданным значения: Значение.Метаданные().Имя для ссылочных объектов.

Получение типа реквизита из метаданных

Объект метаданных реквизита имеет свойство Тип, которое возвращает объект ОписаниеТипов. Это основной способ узнать, какой тип задан реквизиту в конфигураторе, не создавая и не читая данных из базы.

bsl
МетаРеквизит = Метаданные.Справочники.Номенклатура.Реквизиты.Найти("Артикул");
Если МетаРеквизит <> Неопределено Тогда
	ОписаниеТипа = МетаРеквизит.Тип;
	Сообщить("Тип реквизита: " + ОписаниеТипа);
КонецЕсли;

Объект ОписаниеТипов предоставляет метод Типы(), возвращающий массив всех допустимых типов. Для реквизита с единственным типом массив будет содержать один элемент. Проверить, допускает ли реквизит конкретный тип, можно методом СодержитТип(Тип).

Дополнительно ОписаниеТипов хранит квалификаторы: длину строки (КвалификаторыСтроки), точность и разрядность числа (КвалификаторыЧисла), состав даты (КвалификаторыДаты). Это важно, когда нужно узнать не только тип, но и, например, максимальную длину строкового реквизита.

Работа с составным типом и проверка допустимых типов

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

bsl
ОписаниеТипа = Метаданные.Документы.РеализацияТоваровУслуг.Реквизиты.Контрагент.Тип;
Для Каждого ТекТип Из ОписаниеТипа.Типы() Цикл
	Сообщить("Допустимый тип: " + ТекТип);
КонецЦикла;

Если ОписаниеТипа.СодержитТип(Тип("СправочникСсылка.Контрагенты")) Тогда
	Сообщить("Можно записать контрагента");
КонецЕсли;

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

Типы реквизитов табличных частей, форм и динамических списков

Реквизиты табличных частей описываются в отдельной ветке метаданных: Метаданные.Документы.РеализацияТоваровУслуг.ТабличныеЧасти.Товары.Реквизиты.Номенклатура.Тип. Структура обращения та же, что и для шапки объекта, но добавляется уровень табличной части.

Для реквизитов управляемой формы тип определяется иначе. Элемент формы, связанный с данными, хранит путь к данным в свойстве ПутьКДанным, а само описание типов можно получить через РеквизитФормыВЗначение() с последующим анализом метаданных объекта либо через коллекцию ПолучитьРеквизиты() формы: у объекта РеквизитФормы есть свойство ТипЗначения, возвращающее ОписаниеТипов.

bsl
РеквизитыФормы = ЭтаФорма.ПолучитьРеквизиты();
Для Каждого Рекв Из РеквизитыФормы Цикл
	Сообщить(Рекв.Имя + " : " + Рекв.ТипЗначения);
КонецЦикла;

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

Проверка результата и типичные ошибки

После получения типа убедитесь, что используете корректный способ сравнения. Объекты типа Тип сравниваются оператором равенства напрямую — преобразовывать их в строку для сравнения не нужно и вредно: строковое представление зависит от локализации и может отличаться.

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

Ещё одна частая ситуация — попытка получить тип реквизита, которого нет в объекте. Метод Реквизиты.Найти("Имя") возвращает Неопределено, если реквизит не найден, и обращение к свойству Тип вызовет ошибку. Всегда проверяйте результат поиска перед обращением к свойствам.

Выбор подхода под конкретную задачу

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

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

Как выбрать действие

Нужно проверить, что сейчас лежит в переменной или реквизите объектаИспользуйте ТипЗнч(Значение) и сравнение с Тип("ИмяТипа")
Нужно узнать, какие типы разрешены реквизиту в конфигурацииЧитайте Метаданные...Реквизиты.Имя.Тип и работайте с ОписаниеТипов
Нужно отобрать записи по типу поля в выборкеИспользуйте ТИПЗНАЧЕНИЯ() и ССЫЛКА в тексте запроса
Нужен тип реквизита управляемой формыПолучите коллекцию ПолучитьРеквизиты() и прочитайте свойство ТипЗначения

Для отладки удобно выводить тип в сообщения: Сообщить(ТипЗнч(Значение)) покажет читаемое имя типа. В толстом клиенте и конфигураторе тип значения также виден в окне «Вычислить выражение» (Ctrl+W? — нет, Shift+F9) при остановке на точке останова.

Итог

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

ТипЗнч() отвечает за фактический тип значения, свойство Тип метаданных — за допустимые типы реквизита. Составные типы перебираются через ОписаниеТипов.Типы(), а проверка допустимости — через СодержитТип().

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

Как узнать тип значения, если реквизит не заполнен?

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

Как получить имя типа в виде строки?

Простое преобразование Строка(ТипЗнч(Значение)) даст читаемое представление. Для ссылочных значений надёжнее взять Значение.Метаданные().Имя и вид объекта из полного имени метаданных: Метаданные.НайтиПоТипу(ТипЗнч(Значение)).ПолноеИмя().

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

Тип — это один конкретный тип (например, «Число»). ОписаниеТипов — контейнер, который может содержать несколько типов плюс квалификаторы: длину строки, точность числа, состав даты. Именно ОписаниеТипов хранится в свойстве Тип реквизита метаданных.

Как проверить тип поля в запросе?

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

Почему Тип("СправочникСсылка.Контрагенты") вызывает ошибку?

Функция Тип() требует точного имени типа с правильным регистром и существующим объектом метаданных. Ошибка возникает при опечатке в имени справочника или если объект переименован. Сверьте имя в конфигураторе через палитру свойств объекта.

Можно ли получить тип реквизита, не зная заранее имя объекта?

Да, через перебор метаданных: Метаданные.НайтиПоПолномуИмени("Документ.РеализацияТоваровУслуг") вернёт объект метаданных, далее через Реквизиты.Найти(ИмяРеквизита) получите реквизит и его свойство Тип. Так строятся универсальные обработки для любых объектов конфигурации.