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