TGViewer
Frontend Alliance | Автушенко Андрей Frontend Alliance | Автушенко Андрей @frontendalliance · 2.22K subscribers
Post #106 2.78K
Структурная и номинальная типизация

🟣 Номинальная типизация (nominal typing) - это когда совместимость типов определяется по их имени или идентификаторам, а не по внутренней структуре.
Даже если структура одинаковая - типы разные.
Два типа считаются совместимыми, только если они явно связаны иерархией.

Это более строгий и безопасный, но менее гибкий подход по сравнению со структурной типизацией, характерный для языков типа Java и C#.

Рассмотрим пример кода на Java (скрин 1).
У нас есть класс User и класс Admin. И если мы попытаемся создать переменную user типа User и присвоить в нее инстанс класса Admin, то будет ошибка, потому что в джаве номинальная типизация и фактически эти типы разные.

🟣Структурная типизация (structural typing) - это система проверки типов, где совместимость определяется не по имени, а по внутренней структуре.

TypeScript как раз использует структурную типизацию, то есть:

Совместимость типов определяется по структуре - если объект имеет все требуемые свойства и методы, он считается совместимым, независимо от имени типа.

Тот же самый пример (скрин 2).
TypeScript разрешает это присваивание, потому что у обоих типов одна и та же структура (свойство name типа string).

🟣Но мы можем заставить типы в классах вести себя как номинальные, для это нужно добавить приватное поле (скрин 3).

Когда мы объявляем поле с ключевым словом private, то TS применяет ограничение на уровне компиляции. Это означает, что приватное поле может быть доступно только внутри того же класса.

Поэтому два класса, которые имеют приватные поля с одинаковыми именами - структурно несовместимы, так как тайпскрипт будет учитывать "происхождение" приватных полей.

При необходимости номинальное поведение так же можно симулировать через брендирование (расскажу в отдельном посте).

🟣Структурная типизация хоть и считается "гибкой", но может привести к неожиданным проблемам. Рассмотрим следующий пример (скрин 4):

У нас есть тип DatabaseConfig, который имеет обязательное поле url и необязательное поля retries. И тип APIConfig, который также имеет обязательное поле url и необязательно поле timeout.
Есть функция startApi, которая принимает конфиг, который должен быть типа APIConfig.
Но из-за структурной типизации мы можем передать внутрь функции переменную, которая имеет другой тип, так как их структура типов совпала.
ТС это разрешил, но в реальности внутри функции мы не сможем обращаться к полю retries - будет ошибка.

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

✈️ Telegram | 🎓 Менторство | 📹 YouTube | 👩‍💻 Roadmap
  • 🔥 25
  • 👍 8
  • ✍ 7
  • ❤ 3
More from @frontendalliance
  1. Sep 19, 2026Скам на рынке труда Скам в интернете уже давно не удивляет. Но сегодняшний скам паразитиру…
  2. Sep 15, 2026Post #141
  3. Sep 10, 2026Post #140
  4. Aug 21, 2026Post #139
  5. Aug 6, 2026Type refinements: все способы уточнить тип Type Refinement (или уточнение типа) - это проц…
  6. Jun 30, 2026WeakMap и WeakSet На защитах материала у студентов по JavaScript я регулярно вижу один и т…
Threads Profile ViewerView any public Threads profile without an account.Open ThreadLook →Writing with AI? Make it sound human.Metric37 rewrites AI drafts so they read naturally. Free AI detector, 1,500 words free.Try Metric37 →