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