Честно говоря мне немного неловко в 2021 году поднимать тему перехода на строгие проверки типов в таком typescript-frendly сообществе, как angular framework.
Для меня видится очевидным, что новые проекты сейчас - это обязательно typscript c strict:true
, а так же fullTemplateTypeCheck
для angular проектов без Ivy. И strictTemplates
, возможно с некоторыми исключениями, для проектов где Ivy уже есть.
Однако нам всё ещё приходится работать с уже существующей кодовой базой и развивать её. У того кто её начинал могли быть другие стандарты прекрасного. Даже если это были вы. Стоит всё же попытаться перейти на строгую проверку типипов.
Этот доклад ещё раз напомнит о том какие конкретно требования будут предъявляться к вашему коду при повышении строгости. А так же даст набор рекомендаций по тому как их исполнить с преемлемым уровнем страданий.
Прежде чем перейти к сухому коду вспомним что же нам даёт повышение строгости проверок.
Они заставляют нас более корректно и однозначно описывать структуры данных и соблюдать объявленные протоколы.
Angular и TS начинают ругаться на более широкий круг JS-like вольностей, загоняя нас в рамки.
Для большой и долгоживущей кодовой базы сие является благом.
Итак - у вас есть кодовая база с неоправдано либеральными настройками и вы решились на то, чтоб закрутить гайки.
Первым делом стоит повышать строгость Typescript Compiler. Самый простой способ это сделать - это переключить насткойку компилятора strict в значение true.
Что же за ней кроется? Включив strict режим мы включили сразу 7 различных проверок. Можно конечно включать их по отдельности Так же можно отключить некоторые из них уже после включения strict:true, если, например, вдруг поняли что не справляетесь Но безусловно лучше оставить включеными их всех
Тут я хочу вас немного порадовать. Есть несколько проверок, котором ваш Angular код с огромной долей вероятности уже соотвтествует.
alwaysStrict (2.1) аналогичен написанию “use strict” для всего когда учитывая что мы говорим про anguar, то было бы странно если бы мы писали не на классах. А для классов расширенный режим не предусмотрен by design, так что код который сломается по этому пункту встретиться не должен
noImplicitAny
смею предположить, что у большинства из вас подобный запрет из покон веков действует на уровне линтера, так что пожалуй данный переключатель так же можно считать условно бесплатным
отключает подразумевание any как типа "по умолчанию", то есть убирает негласное объяевление небезопасного типа
если ты собрался объявить что-то как any, то должен указать это явно, возможно тебе станет стыдно и ты допишешь более безопасный тайпинг
any - это очень-очень плохо, но что делать если тип неизвестен, а помимо этого ещё и неважен?
например достаточно проверить на Falsy/Truly
используйте unknown - любой тип удовлетворяет unknown, но без явного описания каста к чему-либо не получится отуда что-то достать
Эти флаги повысят качество выведения типов в typescript.
честно говоря по поводу некоторых из них у меня есть вопросы относительно того - а почему это надо дополнительно включать?
noImplicitThis (2.0)
Если функция определена вне объекта/класса, то TS попросит явно указать на что будет ссылаться “this” используя для этого конструкцию с первым псевдо-аргументом с именем “this”. Это позволит избежать ситуаций когда this берётся как any
function getName(name: string): string { return this ? name: 'no context'; } function getName(this: ContextObjectModel, name: string): string { return this ? name: 'no context'; }
Включает проверку типов контекста и аргуметов для функций bind, call и apply
На слайде представлен пример безобразия которое будет проигнорировано компилятором typescript при отключении данного флага
Не уверен в том насколько они часто оказываются нужны в рамках angular разработки, но если понадобятся - хочется быть уверенным, что протоколы будут соблюдены.
Эти флаги отберут у вас возможность подразумевать возможность иметь типы undefined и null как сами собой разумеющиеся. Пожалуй именно этот раздел заставит вас проделать самый большой объём работы. Однако усилия по отказу от этой сладкой возможности - не плодить многочисленные заявления null undefined могут вскрыть существующие проблемы в коде.
Одновременно с тем что они проще всего объясняются - это источник боли, но для того чтоб понять что делать с этой болью стоит придерживаться следующих конвенций: Использование undefined именно как значения - практически всегда неоправдано. Для undefied оставить именно роль только не переданного аргумента для объектных типов в качестве значения "отсутствия значения" горяздо лучше использовать null для number полей в качестве отсутствующего значения лучше испольщовать NaN
Убирает бивариантную проверку для аргументов
до этого функция принимающая потомка заявленого типа аргумента удовлетворяла интерфейсу
теперь