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

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

Определяемый тип в 1С: как обратиться и работать с ним

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

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

На практике вопрос «как обратиться к определяемому типу» возникает в четырёх ситуациях: нужно проверить, входит ли значение в состав определяемого типа; привести значение к конкретному типу из состава; ограничить тип в запросе или СКД; получить само описание типов для программной логики. Каждая задача решается своим инструментом, и ниже разобраны все варианты с примерами кода.

Что такое определяемый тип и где он хранится

Определяемый тип создаётся в конфигураторе в ветке «Общие → Определяемые типы». Внутри него перечислен состав: например, СправочникСсылка.Номенклатура, СправочникСсылка.Контрагенты и Строка(50). Реквизиты объектов, табличных частей и ресурсов регистров могут ссылаться на этот определяемый тип вместо перечисления типов вручную.

Ключевая особенность: определяемый тип существует только на уровне метаданных. Во встроенном языке нет объекта «ОпределяемыйТип», нельзя написать Тип("ОпределяемыеТипы.МойТип") — такой вызов вернёт ошибку. Платформа работает с определяемым типом через его описание типов, которое извлекается из метаданных.

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

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

ОписаниеТипа = Метаданные.ОпределяемыеТипы.ВладелецДополнительныхСведений.Тип;

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

НовоеЗначение = ОписаниеТипа.ПривестиЗначение(ИсходноеЗначение);

Метод ПривестиЗначение вернёт значение, если оно входит в состав типа, или значение по умолчанию (пустую ссылку, Неопределено), если не входит. Это безопасный способ «попробовать привести» без генерации исключения.

bsl
ОписаниеТипа = Метаданные.ОпределяемыеТипы.МойОпределяемыйТип.Тип;
Если ОписаниеТипа.СодержитТип(ТипЗнч(Значение)) Тогда
  Приведенное = ОписаниеТипа.ПривестиЗначение(Значение);
КонецЕсли;

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

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

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

// значение допустимо

КонецЕсли;

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

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

Обращение к определяемому типу в запросах

В языке запросов нельзя указать определяемый тип по имени. Поле составного типа в запросе имеет все типы из состава одновременно, и для работы с конкретным из них применяется оператор ВЫРАЗИТЬ:

ВЫБРАТЬ

ВЫРАЗИТЬ(Документ.Контрагент КАК Справочник.Контрагенты).ИНН КАК ИНН

ИЗ

Документ.РеализацияТоваровУслуг КАК Документ

ГДЕ

Документ.Контрагент ССЫЛКА Справочник.Контрагенты

Здесь два разных механизма. ВЫРАЗИТЬ(.. КАК..) приводит поле к конкретному типу и открывает доступ к его реквизитам через точку — без приведения обращение Документ.Контрагент.ИНН к полю составного типа даст ошибку или развёртывание через соединения со всеми таблицами состава. А условие ССЫЛКА фильтрует записи, где поле хранит ссылку именно нужного вида.

Определяемый тип в СКД и динамических списках

В схеме компоновки данных определяемый тип проявляется как составное поле. При настройке отбора по такому полю пользователь может выбрать вид сравнения с конкретным типом. В тексте запроса СКД действуют те же правила: для доступа к реквизитам — ВЫРАЗИТЬ, для фильтрации — ССЫЛКА.

В динамических списках с произвольным запросом Если нужна сортировка или группировка по реквизиту конкретного типа — снова приводите поле через ВЫРАЗИТЬ в запросе списка.

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

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

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

Типичные ошибки
01
Вызов Тип("ОпределяемыеТипы.Имя") — приводит к исключению, используйте Метаданные.ОпределяемыеТипы.Имя.Тип
02
Обращение к реквизитам составного поля в запросе без ВЫРАЗИТЬ — ошибка или неявные соединения со всеми таблицами состава
03
Жёсткая проверка на один тип вместо СодержитТип — логика ломается при расширении состава определяемого типа
04
Приведение значения без проверки СодержитТип — ПривестиЗначение молча вернёт пустое значение, и ошибка данных останется незамеченной

Как выбрать способ обращения под задачу

Единого «правильного» способа нет — выбор зависит от контекста. Для проверки значения в коде достаточно СодержитТип. Для безопасного приведения — ПривестиЗначение с предварительной проверкой. В запросах и СКД — только ВЫРАЗИТЬ и ССЫЛКА. Для построения универсальных механизмов, обходящих все типы состава, — метод Типы() у описания типов.

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

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

Нужно проверить значение в кодеМетаданные.ОпределяемыеТипы.Имя.Тип.СодержитТип(ТипЗнч(Значение))
Нужно привести значение к определяемому типуОписаниеТипа.ПривестиЗначение(Значение) с предварительной проверкой СодержитТип
Нужно обратиться к реквизиту поля в запросеВЫРАЗИТЬ(Поле КАК КонкретныйТип).Реквизит
Нужно отфильтровать записи по виду ссылки в запросеУсловие Поле ССЫЛКА Справочник.Имя
Нужно перебрать все типы состава программноЦикл по Метаданные.ОпределяемыеТипы.Имя.Тип.Типы()

Проверка результата

После внедрения кода проверьте три вещи. Во-первых, проверка СодержитТип возвращает Истина для всех значений, которые реально встречаются в данных, — выберите типовые документы и прогоните через отладчик. Во-вторых, запрос с ВЫРАЗИТЬ не содержит лишних соединений: посмотрите план запроса в консоли, там должна быть одна таблица приведённого типа, а не все таблицы состава. В-третьих, ПривестиЗначение не возвращает пустые значения там, где ожидались заполненные, — добавьте контроль в журнал регистрации на этапе отладки.

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

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

Проверка типа значения
Норма

СодержитТип возвращает Истина для всех допустимых значений из реальных данных

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

Часть рабочих значений отсекается — состав типа или логика проверки не совпадают

Запрос с приведением
Норма

В плане запроса одно соединение с таблицей приведённого типа

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

Соединения со всеми таблицами состава — ВЫРАЗИТЬ не применён или применён не к тому полю

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

ПривестиЗначение возвращает осмысленное значение

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

Возвращаются пустые ссылки или Неопределено — значение не входит в состав типа

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

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

Можно ли создать значение определяемого типа напрямую?

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

Чем определяемый тип отличается от составного типа реквизита?

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

Работает ли СодержитТип с примитивными типами в составе?

Да. Если в состав входит, например, Строка(50), то СодержитТип(Тип("Строка")) вернёт Истина. Учитывайте, что квалификаторы (длина строки, точность числа) при проверке типа не анализируются — проверяется только сам факт вхождения типа.

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

Через индексацию коллекции метаданных: Метаданные.ОпределяемыеТипы[ИмяСтрокой].Тип. Перед обращением проверяйте, что объект найден (результат не равен Неопределено), иначе при опечатке в имени получите ошибку обращения к свойству.

Почему ВЫРАЗИТЬ не помогает, и запрос всё равно медленный?

Частая причина — ВЫРАЗИТЬ применён в секции ВЫБРАТЬ, но не в условиях соединения или отбора. Приводите поле к конкретному типу везде, где оно участвует: в условии ГДЕ, в условии соединения и в выборке. Также проверьте, что фильтр ССЫЛКА стоит до обращения к реквизитам приведённого поля.

Можно ли использовать определяемый тип в параметрах и возвращаемых значениях функций?

Во встроенном языке нет строгой типизации параметров, поэтому явного указания определяемого типа в сигнатуре нет. Практика — принимать значение, внутри получать описание типа через метаданные и проверять входной параметр через СодержитТип, при несоответствии вызывать исключение с понятным текстом.

Итог

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

Определяемый тип существует только в метаданных: обращайтесь к нему через Метаданные.ОпределяемыеТипы.Имя.Тип. Проверяйте значения методом СодержитТип, приводите через ПривестиЗначение, а в запросах используйте ВЫРАЗИТЬ и ССЫЛКА. Избегайте жёстко зашитых проверок на конкретный тип там, где состав определяемого типа может расширяться.