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

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

Как по описанию типа получить тип в 1С

Как по описанию типа получить тип 1С: методы Тип(), ТипЗнч(), работа с ОписаниеТипов, примеры кода и типичные ошибки разработчиков.

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

Задача «по описанию типа получить тип» возникает в типовых сценариях: при программном создании реквизитов, при работе с запросами и СКД, при проверке значений на соответствие ограничениям, при динамическом построении таблиц значений. Способ решения зависит от того, что именно у вас есть на входе: строка с именем типа, готовый объект ОписаниеТипов или реквизит метаданных.

Ниже разобраны рабочие приёмы: получение типа из строкового имени, извлечение единственного типа из описания, обход составных описаний, а также проверка значения на соответствие описанию типов. Все примеры написаны на встроенном языке 1С и работают как на толстом, так и на тонком клиенте, если не указано иное.

Получение типа по строковому имени через функцию Тип()

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

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

ТипЧисло = Тип("Число");

ТипСтрока = Тип("Строка");

ТипДокумент = Тип("ДокументСсылка.РеализацияТоваровУслуг");

Для примитивных типов используются короткие имена: Число, Строка, Дата, Булево. Для ссылочных типов имя строится по шаблону ВидОбъекта.ИмяОбъекта: СправочникСсылка.Контрагенты, ПеречислениеСсылка.СтавкиНДС, ПланВидовХарактеристикСсылка.ДополнительныеРеквизиты. Ошибка в имени приведёт к исключению времени выполнения, поэтому строку лучше формировать из метаданных, а не писать вручную.

bsl
Функция ПолучитьТипПоИмени(ИмяТипа)
	Попытка
		Возврат Тип(ИмяТипа);
	Исключение
		Возврат Неопределено;
	КонецПопытки;
КонецФункции

Извлечение типа из объекта ОписаниеТипов

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

ОписаниеТипа = Новый ОписаниеТипов("СправочникСсылка.Номенклатура");

МассивТипов = ОписаниеТипа.Типы();

Если МассивТипов.Количество() = 1 Тогда

ИскомыйТип = МассивТипов[0];

КонецЕсли;

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

МетаданныеРеквизита = Метаданные.Справочники.Номенклатура.Реквизиты.Артикул;

ОписаниеТипа = МетаданныеРеквизита.Тип; // это ОписаниеТипов

ТипРеквизита = ОписаниеТипа.Типы()[0]; // а это уже Тип

Работа с составными описаниями типов

Реквизит может иметь составной тип — например, ссылку либо на справочник «Контрагенты», либо на «ФизическиеЛица». В этом случае метод Типы() вернёт массив из нескольких элементов, и брать только первый элемент некорректно: вы потеряете часть допустимых типов.

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

ОписаниеТипа = Метаданные.Документы.ЗаказПокупателя.Реквизиты.Плательщик.Тип;

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

Сообщить(ТекущийТип);

КонецЦикла;

// Проверка конкретного типа

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

// тип входит в состав описания

КонецЕсли;

Типичные ошибки
01
Взять Типы()[0] у составного описания и потерять остальные допустимые типы — проверки значений начинают ложно отклонять корректные данные
02
Сравнивать ОписаниеТипов с Типом напрямую через знак равенства — объекты разных видов никогда не равны
03
Хардкодить имя типа строкой без обработки исключения — переименование объекта в конфигурации приводит к падению кода

Проверка значения на соответствие описанию типа

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

ОписаниеТипа = Новый ОписаниеТипов("Число", , , Новый КвалификаторыЧисла(10, 2));

Результат = ОписаниеТипа.ПривестиЗначение("123,456"); // 123.46 — приведено и округлено

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

Функция ЗначениеСоответствуетОписанию(Значение, ОписаниеТипа)

Возврат ОписаниеТипа.СодержитТип(ТипЗнч(Значение));

КонецФункции;

Контрольные точки

Как проверить результат

Состав массива Типы()
Норма

Количество элементов равно ожидаемому числу типов реквизита

Тревожный признак

Ноль элементов или больше, чем задано в конфигураторе

Приведение значения
Норма

ПривестиЗначение() вернуло значение нужного типа

Тревожный признак

Вернулось значение по умолчанию — значение не соответствует описанию

Сравнение типов
Норма

ТипЗнч(Значение) равен извлечённому типу

Тревожный признак

Сравнение даёт Ложь при визуально совпадающих типах — проверьте, не сравниваете ли вы Тип с ОписаниеТипов

Обратная задача: получить описание типа по типу или строке

Иногда требуется обратное преобразование — из типа или строки с именем получить ОписаниеТипов, например чтобы добавить колонку в таблицу значений. Конструктор Новый ОписаниеТипов() принимает как строку с перечислением типов через запятую, так и массив объектов типа.

// Из строки

Описание1 = Новый ОписаниеТипов("СправочникСсылка.Номенклатура");

// Из массива типов

МассивТипов = Новый Массив;

МассивТипов.Добавить(Тип("Число"));

МассивТипов.Добавить(Тип("Строка"));

Описание2 = Новый ОписаниеТипов(МассивТипов);

// Из существующего описания с добавлением типа

Описание3 = Новый ОписаниеТипов(Описание1, "ДокументСсылка.ЗаказПокупателя");

Квалификаторы передаются третьим и четвёртым параметрами конструктора: КвалификаторыЧисла, КвалификаторыСтроки, КвалификаторыДаты. Они действуют только на соответствующие типы в составе описания и игнорируются для ссылочных типов.

Порядок действий для произвольного реквизита
  1. 1
    Получите объект метаданных реквизита через Метаданные
  2. 2
    Прочитайте свойство Тип — это ОписаниеТипов
  3. 3
    Вызовите Типы() и проверьте количество элементов массива
  4. 4
    Если тип один — возьмите Типы()[0], если составной — обработайте массив целиком
  5. 5
    Проверьте результат сравнением с ТипЗнч() контрольного значения

Типичные сценарии и границы применения

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

В расширениях конфигурации и внешних обработках функция Тип() работает с типами основной конфигурации, но обращение по строковому имени к типу, которого нет в текущем сеансе (например, объект добавлен в расширении, а код выполняется в контексте основной базы), вызовет ошибку. Для устойчивого кода всегда оборачивайте вызов в попытку или проверяйте наличие объекта через Метаданные.НайтиПоПолномуИмени().

FAQ

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

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

Как получить тип из поля запроса программно?

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

Почему Тип("Справочник.Номенклатура") выдаёт ошибку?

Для функции Тип() ссылочные типы указываются со словом «Ссылка»: СправочникСсылка.Номенклатура. Форма «Справочник.Номенклатура» допустима только в языке запросов, и это частый источник путаницы при переносе имён между кодом и текстом запроса.

Как сравнить два типа между собой?

Объекты типа сравниваются обычным оператором равенства: ТипЗнч(Значение) = Тип("Число"). Сравнивать напрямую ОписаниеТипов с Типом нельзя — сначала извлеките типы методом Типы().

Можно ли получить тип по строке, введённой пользователем?

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

Что вернёт ПривестиЗначение(), если значение не подходит?

Метод вернёт значение по умолчанию для первого подходящего типа описания: пустую ссылку, ноль, пустую строку или пустую дату. Исключения не возникает, поэтому факт неудачного приведения нужно проверять отдельно через СодержитТип().

Итог

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

Тип получают из строки функцией Тип(), а из ОписаниеТипов — методом Типы(). Свойство Тип реквизита метаданных возвращает именно описание, а не тип. Для составных описаний обрабатывайте весь массив, для проверки значений используйте СодержитТип() и ПривестиЗначение(). В запросах действует отдельный синтаксис имён типов без слова «Ссылка».