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