Комментарии 10
Тайп-фашизм ничем не лучше любого другого вида абсолютизма. Иногда функция проста как карандаш, не завязана жестко на тип, и, при этом, не торчит во внешний API. И использовать any, в таких случаях, лучше чем городить многоэтажный огород. Непримиримые борцы с any - смешны.
Если значение просто прокидывается, то есть тип unknown, а для всех остальных случаев можно объявить обобщенный тип, необходимый функции. Но значимость типов куда выше. Допустим, что функция проста, если она ничего не возвращает - это пол беды, но если она возвращает any, то вся типизация сыпется, надеюсь, это не нужно пояснять.
P.S.: Минус не мой.
Ответил ниже, но вам тоже напишу. Я совсем не новичок в TS, и конечно знаю про unknown и все рекомендации. Немного раскрою про рантайм. Обычно на этом месте приводят пример с данными с сервера, но, как мне кажется, с сервером все проще: данные, скорее всего, будут нормализованы и описать их типы не представляет проблем. Приведу другой пример. Представьте, что вы делаете встраиваемый виджет, в логике которого вы планируете получить коллекцию DOM-элементов снаружи вашего решения (из хост-приложения). А там, внезапно, кастомные элементы, о типах которых, вы не знаете вообще ничего.
const arr = [];
// через n строк; массив заполнен
arr[0].foo.bar;
// cannot get property bar of undefined
В проектах, над которыми я работал, ребятам тоже было лень поставить аннотацию. А потом все вместе весело ловили вот такие баги, как выше, вместо ошибок компиляции.
К сожалению, разработчики TS при всех успехах упорно не желают делать даже опциональную поддержку глубокого вывода типов, мол, все будет безумно медленно. Лично я хотел бы иметь строгий режим для компилятора с глубоким выводом, да и работает же как-то в других языках, просто у них там странная философия своя. Из-за этого типы в TS не совсем полноценны даже в compile-time, что прискорбно.
Во первых, чем принципиально отличаются ошибки рантайма от ошибок компиляции? Тесты писать не надо?
Во вторых, вы привели уж совсем детский кейс, где any использовать либо глупо, либо вопрос можно решить за счет conditional chaining, либо использовать unknown или проброс типов.
В третьих, раз уж вы привели пример с коллекциями, посмотрите как в TS реализованы декларации для работы, например, с DOM API (стандартный dom.d.ts). Есть стандартный querySelectorAll, где описаны возвращаемые типы через маппинг имен тегов к конструкторам элементов. Вот только согласно W3C стандартам, селекторы могут не содержать имен тегов, а сами теги, внезапно, могут быть экземплярами CustomElements. Для всех неопознанных типов, возвращается тип Element, который, как вы понимаете, совсем не то, что мы можем ожидать. И вот представьте, что вы разработчик библиотек для работы с DOM API, и вам предстоит бороться с такой несогласованностью стандартов и реализаций. Дженерики и unknown работают не всегда и не всегда так просто, как это требуется для решения какой-то частной задачи.
В четвертых, есть еще и типы рантайма.
Во первых, чем принципиально отличаются ошибки рантайма от ошибок компиляции?
В данном случае - местом возникновения. Ошибка типов времени компиляции намного ближе к месту настоящей ошибки программиста.
В третьих, раз уж вы привели пример с коллекциями, посмотрите как в TS
реализованы декларации для работы, например, с DOM API (стандартный
dom.d.ts).
За работой команды TS слежу не слишком плотно, но точно видел активную работу над тем, чтобы можно было без костылей подключать свои тайпинги для DOM. Но, конечно, жалко, что при дизайне DOM API не задумывались о вопросах типизации, а думали только про JS и (на совсем ранних этапах) про Java, в которой тогда ещё не было дженериков.
В целом, моя позиция такова: any - это крайний случай, когда уж совсем ничего другого нормально не написать. Он имеет слишком неприятное свойство "заражать" код (большинство операций с any дают any на выходе), и делает систему типов неконсистентной (он одновременно и top, и bottom, грубо говоря).
Стоило добавить, что документация TS рекомендует использовать объединения типов и значения по умолчанию для функций и методов вместо перегрузки.
TypeScript тип any против всех