В каждом проекте свои правила и подходы в типизации данных. Некоторые из них общепринятые, кое-какие сомнительны, а иные  не достаточно строги. В данной статье предлагается объективный взгляд на законы, придуманные разработчиками для использования TypeScript. 1. Как типизировать данные2. Как понимать типы3. Как использовать типизацию4. Глубокая типизация5. Связанная типизация6. Изящная типизация Именование типов следует тем же правилам, что и именования переменных: своим названием они должны объяснять, какую сущность содержит переменная такого типа. Типы принято писать с большой буквы. Иногда используют префиксы и постфиксы для разных типов. Код 3.1. Префиксы и постфиксы в именах типов В целом префиксы не несут никакого особого смысла. Как показано в Коде 1.5 из статьи "Как типизировать данные" имена из контекста значений и контекста типов не конфликтуют. А описание того, что за сущность содержится в типе ложится на плечи основной части имени. Тем более префиксы не нужны, чтобы определить что перед нами переменная или тип - контексты значений и типов не пересекаются. Конфликт имён типов и переменных возникает при импорте типа и React-компонента. Данная ситуация не редкость для React-приложений и легко решается: Код 3.2. Импортирование типа и компонента с одинаковыми именами Стоит задуматься о необходимости уникального имени типа в рамках проекта. Не всегда комфортно, введя в поиск имя компонента, видеть в результатах мешанину из типов и переменных. Но когда вы типизируете пропсы для компонента, вряд ли вам понадобится уникальное имя для типа, который используется только в одном месте. Следуя принципу единообразия, нужно именовать типы, как это принято на проекте, но если у вас есть возможность выбирать, используйте здравый смысл. Доступность типов следует блочной модели. Но в большинстве проектов типы описываются на уровне модуля, сразу после импортов. Это соответствует цели не засорять логику кодом типизации. Тип переменной конечно описывается рядом с ней, но если он имеет довольно ёмкое описание, то лучше вынести его в отдельный type на уровень модуля. Соответственно, если в модуле для логики слишком много описанных типов, то их удобно так же вынести в отдельный файл, а разросшийся файл с типами разбить на несколько. Границы, где происходит решение о выносе типа выше, определяются здравым смыслом, но на некоторых проектах присутствуют конкретные правила. Например, выносить все типы из файлов логики и импортировать их или писать один-два типа для файла компонента, но если типов больше, выносить в отдельный файл. type умеет почти всё, что умеет interface и немного больше. Полный отказ от interface не приводит к проблемам в большинстве проектов. Interface умеет редекларировать ранее описанный тип, что в редких случаях полезно для расширения типизации: Код 3.3. Повторная декларация interface Array добавляет в него новый метод findLast (тип описан по примеру метода find). Если же вы пишете библиотеку общего пользования, то можете писать interface в тех случаях, когда хотите позволить изменять пользователям кода ваши типы. В библиотеках на TypeScript куда важнее связывать используемые типы, чтобы пользователю не приходилось страдать от замечаний анализатора. О связанных типов будет рассказано в следующих статьях. Отказаться от type не получится, так как он используется в объединении и пересечении типов, что является очень полезной возможностью. Но разработчик свободен в выборе способов типизации и конечно же стоит следовать принятым практикам на проекте. Тип any вреден тем, что по своей сути не типизирует данные. Он удобен при переходе проекта с JavaScript на TypeScript, пока разработчики постепенно типизируют новый код, старый код, не должен краснеть ошибками. Отсутствие в коде any ещё не означает, что он не используется, так как этот тип неявно проставляется в параметры и другие переменные, чей тип анализатор не может определить по коду. Код 3.4. Параметры неявно принимают тип any В этой ситуации запрет any через линтеры немного наивен. Кроме того иногда наш код готов работать с любым типом. Тогда можно прописать тип unknown. Анализатор, увидев этот тип, будет следить за тем, чтобы при передаче такой переменной происходило сужение типа до требуемого (что можно сделать через условия или защитники типа). Код 3.5. Примеры сужения типа unknown различными способами Оператор сужения типа as  называют хаком типизации. Он искусственно сужает тип, чтобы переменной более узкого типа можно было присвоить значение более широкого. Код 3.6. Сужение типа string | null к типу string с помощью оператора as Сужение типа переменных должно происходить естественно как показано в коде 3.5, чтобы анализатор мог проверить правильно использования переменной в разных участках кода и подсветить ошибки. Есть ситуации, когда анализатор не способен определить тип и тогда as является не только не запрещённым, но и правильным решением. В литературе пишут, что прописывая as, разработчик как бы говорит "TypeScript, я гарантирую, что здесь такой тип". Но учитывая, насколько неправильно разработчики используют as, эта фраза скорее звучит так: "TypeScript, заткнись! Я лучше тебя знаю, какой здесь должен быть тип". Эти ситуации имеют конкретные причины: TypeScript не может определить тип в результате парсинга JSON, строк или ArrayBuffer, так как  хранимые в них данные имеют более узкие типы, чем возвращают методы и нет возможности заранее это узнать; типизация нативных или библиотечных функций такова, что не позволяет вывести из входных данных более узкие типы (например reduce). Разработчик не может повлиять на их типы и вынужден преобразовывать результат через as.  Код 3.7. Примеры, где as помогает сужать тип В большинстве случаях, где разработчики сами пишут типизацию данных и функции, можно обойтись без оператора as. Для этого нужно выяснить, почему тип переменный не сузился до нужного множества значений. Обычно причина в плохой типизации исходного значения или отсутствии проверок для переменной. Часть решений будут рассмотрены в следующих статьях. Функции могут быть типизированы различными способами: Код 3.8. Типизация функций различными способами Излишне использовать все эти способы одновременно. Кроме того, тип возвращаемого значения может быть вычислен анализатором TypeScript.  Использование дженериков, единого типа для функции или для аргументов даёт интересные возможности, которые будут рассмотрены в следующих статьях. Библиотеки предоставляют типы для работы со своими данными. Прежде, чем придумывать новый тип, проверьте в файлах декларации d.ts предоставленные типы, возможно похожий тип уже есть и логичнее использовать его. Код 3.9. Типизация React-компонента С увеличением опыта работы с библиотеками разработчик узнаёт о предоставляемых ими типах. Так же не следует пренебрегать утильными типами, существующие в самом языке TypeScript.  Код 3.10 Пример использования утильных типов Перечисленные подходы в разработке приложения позволяют анализатору TypeScript работать в полную силу. Язык TypeScript предоставляет намного больше возможностей, которые очень практично и изящно можно использовать в приложении.  Следующая статья TypeScript в React-приложениях. 4. Глубокая типизация