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