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

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

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

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

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

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

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

Что такое ОписаниеТипов и почему тип нельзя получить напрямую

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

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

Основной способ: метод Типы()

Метод Типы() возвращает массив объектов типа Тип. Если описание содержит один тип, достаточно взять первый элемент массива:

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

ТипСтроки = Описание.Типы()[0]; // Тип "Строка"

Сообщить(ТипСтроки = Тип("Строка")); // Истина

Если описание получено из метаданных реквизита, логика та же:

МетаданныеДокумента = Метаданные.Документы.РеализацияТоваровУслуг;

ОписаниеРеквизита = МетаданныеДокумента.Реквизиты.Комментарий.Тип;

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

Перед обращением к элементу с индексом 0 полезно проверить, что массив не пуст. Пустое описание типов встречается редко, но при динамическом построении объектов такая ситуация возможна, и обращение к несуществующему элементу вызовет ошибку выполнения.

bsl
ТипыОписания = Описание.Типы();
Если ТипыОписания.Количество() > 0 Тогда
    ПервыйТип = ТипыОписания[0];
КонецЕсли;

Проверка типа значения без извлечения массива

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

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

ТипЗначения = ТипЗнч(НекоеЗначение);

Если Описание.СодержитТип(ТипЗначения) Тогда

// Значение соответствует описанию типов

КонецЕсли;

Этот подход надёжнее сравнения с Типы()[0], потому что корректно работает с составными типами: не нужно перебирать массив вручную и не возникает ошибки, когда тип значения находится не на первой позиции.

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

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

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

Если ТекущийТип = Тип("Строка") Тогда

// обработка строкового типа

ИначеЕсли Справочники.ТипВсеСсылки().СодержитТип(ТекущийТип) Тогда

// это ссылка на справочник

КонецЕсли;

КонецЦикла;

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

Как получить имя типа строкой

Иногда нужно не сравнение, а текстовое представление типа — для логирования или построения описания через строку. Имя ссылочного типа можно получить через метаданные:

Если Справочники.ТипВсеСсылки().СодержитТип(ТекущийТип) Тогда

ПустаяСсылка = Новый(ТекущийТип);

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

КонецЕсли;

Конструктор Новый(Тип) для ссылочных типов создаёт пустую ссылку без обращения к базе данных, поэтому такой способ получения метаданных работает быстро и безопасно даже в цикле.
ПЗ
Практическое замечание

Получение типа через приведение значения

Альтернативный путь — не извлекать тип, а привести значение к описанию методом ПривестиЗначение() и затем определить тип результата через ТипЗнч():

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

ПриведенноеЗначение = Описание.ПривестиЗначение("123,45");

// ТипЗнч(ПриведенноеЗначение) = Число

Этот способ полезен, когда реальная задача — не получить тип, а гарантировать, что значение соответствует описанию. ПривестиЗначение() обрезает строки по квалификаторам, округляет числа и преобразует значения к первому подходящему типу из описания. Если значение привести нельзя, для ссылочных типов возвращается пустая ссылка, для примитивных — значение по умолчанию (0, пустая строка, пустая дата).

Типичные ошибки при получении типа из описания

Первая распространённая ошибка — попытка сравнить само описание типов с типом: Описание = Тип("Строка"). Такое сравнение всегда ложно, потому что сравниваются объекты разных видов. Сравнивать нужно элементы массива Типы().

Вторая ошибка — обращение к Типы()[0] без проверки количества элементов. При пустом описании это вызывает исключение и останавливает выполнение кода, что особенно неприятно в фоновых заданиях и обменах данными.

Третья ошибка — сравнение типов через строковое представление: Строка(Тип) = "СправочникСсылка.Номенклатура". Строковое представление зависит от локализации и не гарантирует стабильного формата. Надёжное сравнение — только через объекты типа Тип.

Типичные ошибки
01
Сравнение самого объекта ОписаниеТипов с типом — результат всегда Ложь, проверка молча не работает
02
Обращение к Типы()[0] без проверки Количество() > 0 — исключение при пустом описании
03
Сравнение типов через Строка(Тип) — нестабильный формат, ошибки после смены локали
04
Игнорирование составного типа: берётся первый элемент массива, хотя значение имеет другой тип из описания

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

После получения типа убедитесь, что он соответствует ожиданиям. Основные контрольные точки: тип найден, сравнение с эталонным типом даёт Истина, приведённое значение имеет ожидаемый тип.

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

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

Описание.Типы().Количество()
Норма

Больше 0 — типы есть, можно брать элемент по индексу

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

0 — описание пустое, обращение по индексу вызовет ошибку

Описание.Типы()[0] = Тип("Строка")
Норма

Истина — тип извлечён корректно

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

Ложь — проверьте, как создавалось описание, возможно тип составной

ТипЗнч(Описание.ПривестиЗначение(Значение))
Норма

Совпадает с ожидаемым типом из описания

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

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

Краткий итог

Получить тип из описания типов в 1С можно тремя путями: извлечь массив через Типы() и взять нужный элемент, проверить вхождение типа методом СодержитТип() без извлечения или привести значение через ПривестиЗначение() и определить тип результата. Для одиночных типов достаточно Типы()[0] с проверкой количества, для составных — перебор массива или СодержитТип().

Итог

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

ОписаниеТипов хранит массив типов, а не один тип. Используйте Типы()[0] для одиночного типа, СодержитТип() — для проверки вхождения, ПривестиЗначение() — когда нужно само значение, а не тип. Всегда проверяйте Количество() перед обращением по индексу.

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

Можно ли получить тип из ОписаниеТипов без метода Типы()?

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

Как проверить, что описание содержит только один тип?

Сравните количество элементов: Описание.Типы().Количество() = 1. Это полезно перед тем, как брать Типы()[0] и считать описание однотипным — иначе логика может скрыто игнорировать остальные типы составного описания.

Как получить тип реквизита объекта метаданных?

Через свойство Тип реквизита: Метаданные.Справочники.Номенклатура.Реквизиты.Артикул.Тип вернёт ОписаниеТипов, из которого дальше извлекается конкретный тип методом Типы().

Почему сравнение Типы()[0] = Тип("СправочникСсылка.Номенклатура") возвращает Ложь?

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

Как из строки с именем типа получить объект Тип?

Функцией Тип("ИмяТипа"), например Тип("Строка") или Тип("СправочникСсылка.Номенклатура"). Если имя сформировано неверно или такого типа нет в конфигурации, будет вызвано исключение, поэтому динамические имена типов стоит проверять через попытку или по метаданным.

Учитывает ли СодержитТип() квалификаторы строки и числа?

Нет, метод проверяет только сам тип. Строка любой длины пройдёт проверку для описания Строка(10). Если важны квалификаторы, дополнительно сравнивайте свойства КвалификаторыСтроки и КвалификаторыЧисла у описания типов.