Цена TypeScript

https://medium.com/javascript-scene/the-typescript-tax-132ff4cb175b
  • Перевод
В 2017-2019 годах можно было наблюдать серьёзный рост TypeScript. Происходило это по вполне понятным причинам. В этом языке есть много хорошего. Почти половина респондентов исследования State of JavaScript 2018 года уже пробовали TypeScript и собираются писать на нём в будущем. TypeScript весьма популярен, но стоит ли использовать его в крупномасштабных программных проектах?



В этом материале предпринята попытка достаточно строго, опираясь на числовые показатели и практический опыт автора, проанализировать эффект от использования TypeScript при разработке больших проектов.

О росте TypeScript


TypeScript — это один из самых быстрорастущих языков. В настоящее время это — ведущий язык из тех, которые компилируются в JavaScript. Вот данные по TypeScript из Google Trends.


Данные Google Trends за 2014-2019 годы по динамике популярности TypeScript

Ниже показаны сведения с GitHub, отражающие интерес программистов к работам по развитию различных языков программирования.


Данные GitHub по росту языков программирования с точки зрения числа контрибуторов

Выше представлены весьма впечатляющие показатели, указывающие на рост популярности TypeScript, которые нельзя недооценивать. Но при этом надо отметить, что TS ещё далёк от того, чтобы его можно было бы признать ведущим языком экосистемы JavaScript. Если экосистему JavaScript сравнить с океаном, то TypeScript будет большой волной в этом океане. Вот сравнение JavaScript (красная линия) и TypeScript (синяя линия) по данным Google Trends.


Данные Google Trends за 2014-2018 годы по динамике популярности JavaScript и TypeScript

А вот сведения с GitHub о ведущих языках программирования, использованных при создании репозиториев в 2008-2018 годах.


Данные GitHub по количеству репозиториев, созданных с использованием различных языков программирования

Можно заметить, что, по числу репозиториев, TypeScript не входит в первую пятёрку языков.

При этом надо отметить, что в 2018 году произошёл переломный момент в истории TypeScript, и в 2019 году этот язык будет использоваться во множестве реальных проектов. Если вы являетесь JavaScript-разработчиком, то у вас, в таких условиях, просто не будет выбора. Решение об использовании TypeScript в некоем проекте, над которым вам придётся работать, уже, без учёта вашего мнения, будет принято. При этом не нужно бояться изучать и использовать TypeScript.

Однако если вы — тот, кто принимает решение о том, какой язык использовать в некоем проекте, то вам нужно иметь реалистичное понимание сильных и слабых сторон TypeScript. Вам, принимая решения, нужно будет понять — хорошо или плохо отразится на проекте выбор TypeScript.

Мой опыт подсказывает, что у TypeScript есть свои плюсы и минусы, но нельзя говорить о том, что его использование, в целом, оказывает положительное влияние на проекты. TypeScript пришёлся по душе многим разработчикам, и с этим языком связано много такого, что мне, испытавшему его на практике, действительно нравится. Но за всё надо платить.

Предыстория


Я пришёл в JavaScript из мира статически типизированных языков — таких, как C/C++ и Java. В первое время мне было тяжело приспособиться к динамической типизации, принятой в JavaScript, но как только я к ней привык, я почувствовал себя человеком, который дошёл до выхода длинного тёмного туннеля и увидел свет. У статической типизации немало позитивных черт, но то же самое можно сказать и о динамической типизации.

В последние несколько лет я периодически с головой погружался в TypeScript-разработку. В результате у меня набралось больше года TypeScript-практики. Я руководил несколькими крупными командами, использующими TypeScript в качестве основного языка. Это позволило мне оценить воздействие TypeScript на разработку больших проектов и сравнить подобные проекты с похожими проектами, в которых использовался обычный JavaScript.

В 2018 можно было наблюдать взлёт децентрализованных приложений. В большинстве таких приложений использовались смарт-контракты и опенсорсные решения. При разработке приложений для интернета ценностей (Internet of value) ошибки в программах могут стоить пользователям денег. Сейчас, как никогда, важно писать надёжный код. Так как подобные проекты обычно бывают опенсорсными, я подумал, что то, что мы используем в разработке TypeScript — это хорошо, так как благодаря этому другим TypeScript-командам будет легче работать с нашими решениями, и, в то же время, благодаря этому обеспечивается совместимость нашего кода с проектами, в которых используется JavaScript.

В процессе практического использования TypeScript я значительно лучше стал понимать преимущества и недостатки этого языка. Мне стало понятным и то, какое влияние выбор TypeScript может оказать на программный проект. Мне с сожалением приходится говорить о том, что опыт работы с TypeScript оказался не таким успешным, как мне того хотелось. Если TypeScript не будет значительно улучшен, то я не стану выбирать этот язык для другого крупномасштабного проекта.

Сильные стороны TypeScript


TypeScript, в долгосрочной перспективе, всё ещё кажется мне позитивным явлением. Я хочу любить этот язык, и некоторые его черты мне всё ещё, безусловно, нравятся. Я надеюсь, что разработчики TypeScript и его сторонники увидят в этом материале конструктивную критику, а не беспочвенные нападки на этот язык. Разработчики TypeScript могут исправить некоторые из его недостатков, и, если они это сделают, я могу повторить мой анализ эффективности этого языка и прийти к другим результатам.

Статическая типизация может быть весьма полезной в том плане, что она помогает документировать функции, делает код понятнее и уменьшает когнитивную перегрузку программиста. Например, я обычно нахожу систему типов Haskell помогающей работать, не требующей излишних затрат времени и сил, удобной, ненавязчивой. Но иногда даже гибкая система типов Haskell и его типы высших родов (higher-kinded type) мешают работать. Попытайтесь, например, типизировать трансдьюсер средствами Haskell или TypeScript. Сделать это непросто, и, возможно, результат окажется немного хуже чем его нетипизированный эквивалент.

Мне нравится то, что в TypeScript аннотации типов, в том случае, если они мешают, могут быть необязательными. Мне нравится то, что в TypeScript используется структурная типизация, и то, что тут имеется некоторая поддержка вывода типов (хотя в этой сфере есть множество возможностей для улучшений).

TypeScript поддерживает интерфейсы, которые подходят для повторного использования (в отличие от встроенных описаний типов). Интерфейсы можно по-разному применять для аннотирования API и сигнатур функций. У одного интерфейса может быть много реализаций. Интерфейсы — это одна из лучших возможностей TypeScript и мне хотелось бы, чтобы нечто подобное появилось бы в обычном JavaScript.

Одна из сильнейших сторон TypeScript заключается в его инструментарии. Например, использование подходящего редактора (вроде Atom или Visual Studio Code), для которого созданы качественные TS-плагины, даёт в распоряжение разработчика лучшие из существующих в экосистеме JavaScript инструменты. Разработчикам других плагинов стоит изучить TS-плагины и подумать над тем, как, используя идеи, заложенные в них, они могут улучшить свои разработки.

Анализ эффективности TypeScript


Сейчас я собираюсь оценить TypeScript по нескольким показателям, выставляя оценки в диапазоне от -10 до 10. Это поможет вам лучше понять то, насколько хорошее (или плохое) влияние может оказать TypeScript на большие проекты.

Если оценка по показателю превышает 0 — это говорит о позитивном воздействии TypeScript на проект. Если оценка меньше 0 — это указывает на негативное воздействие. Значение оценки в 3-5 баллов говорит о достаточно сильном воздействии. 2 балла указывают на среднее воздействие. 1 балл — сравнительно слабое воздействие.

Те цифры, которыми я буду далее оперировать, сложно измерить точно. Я в своих оценках буду, в некоторой степени, субъективен. Но я постарался сделать эти оценки такими, чтобы они как можно более реалистично раскрывали плюсы и минусы использования TypeScript в реальных проектах.

Все проекты, которые я анализировал, выставляя оценки, содержали более 50 тысяч строк кода. Они явились плодом работы нескольких программистов в течение нескольких месяцев. Один из этих проектов основан на Angular 2, в нём использовался TypeScript. Он сравнивался с похожим проектом, написанным с применением Angular 1 и обычного JavaScript. Все остальные проекты созданы на базе React и Node с применением TypeScript. Они сравнивались с аналогичными проектами, в которых использовался обычный JavaScript. Некоторые показатели, наподобие плотности ошибок (bug density), были оценены лишь приблизительно. Все команды, работавшие над проектами, состояли из опытных и начинающих TypeScript-разработчиков. У всех членов таких команд была возможность взаимодействия с более опытными наставниками, которые помогали им адаптироваться в сфере TypeScript-разработки.

Объективные данные, которыми я располагаю, за счёт небольшого объёма выборки, слишком разнородны, в них слишком много шума, поэтому на их основе нельзя вынести какие-то определённые объективные суждения, которые можно было бы выносить, опираясь на достаточно точные цифры и не рискуя слишком сильно ошибиться. Один проект на JavaScript продемонстрировал плотность ошибок, попавших в продакшн, на 41% меньше, чем сравнимый проект на TypeScript. В другом сравнении проект на TypeScript показал на 4% меньшую плотность ошибок, чем в сравнимом проекте на JavaScript. В данном случае очевидно то, что на число ошибок, добравшихся до стадии выпуска продукта, гораздо сильнее влияет не использование в проекте TypeScript, а наличие или отсутствие других мер по обеспечению качества кода. Это искажает показатели до такой степени, что пользоваться ими становится невозможно.

Столь широкий разброс объективных показателей привёл к тому, что я решил их не использовать, сосредоточившись на темпах реализации возможностей проектов и на наблюдениях, указывающих на те области жизненного цикла проектов, в которых тратилось больше всего времени. Ниже, анализируя показатели, мы поговорим об этом подробнее.

Так как в моём анализе присутствует сильная субъективная составляющая, вам нужно учитывать возможность наличия неточностей в интерпретации показателей (это отражено на схеме). Но общие выводы этого анализа способны показать реалистичную картину того, чего можно ждать от использования в некоем проекте TypeScript.


Анализ эффективности TypeScript

Я уже могу слышать возражения, касающиеся низких оценок преимуществ TypeScript, и, честно говоря, я не могу полностью отвергать эти возражения. TypeScript, на самом деле, даёт программисту некоторые очень полезные, мощные возможности. По этому поводу не может быть никаких сомнений.

Для того чтобы понять причину появления в моём анализе сравнительно низких и редких положительных оценок, следует хорошо понять то, с чем именно я сравниваю TypeScript. Это не «просто JavaScript», а JavaScript и инструменты, созданные для эффективной разработки на этом языке.

Рассмотрим показатели, приведённые на схеме.

▍Инструменты разработчика (Developer Tooling)


Инструментарий — это моя любимая возможность TypeScript, представляющая, вероятно, самое сильное практическое преимущество использования данного языка. Благодаря качественному инструментарию снижается когнитивная нагрузка на разработчика. В его распоряжении оказываются подсказки по типам интерфейсов, в процессе работы, в режиме реального времени, отлавливаются потенциальные ошибки. Если бы при разработке на обычном JavaScript с использованием хороших плагинов ничего подобного бы не было, я бы дал TypeScript более высокую положительную оценку. Но в нашем случае 0 очков — это то, чем уже можно пользоваться, программируя на JavaScript, то есть то, с чем мы сравниваем TypeScript, уже находится на довольно высоком уровне.

Большинство защитников TypeScript, как кажется, не очень хорошо понимают то, с чем именно конкурирует TypeScript. Речь идёт о том, что выбор инструментария — это не принятие решения о том, нужно ли использовать TypeScript или JavaScript без каких-либо вспомогательных инструментов. Речь идёт о выборе между TypeScript и всей богатой экосистемой инструментов для JavaScript-разработки. Средства автозавершения кода и обнаружения ошибок для обычного JavaScript дают 80-90% того, что обычно считают сильными сторонами TypeScript. Происходит это, например, при использовании средств для автозавершения кода, инструментов для вывода типов и линтеров. При использовании системы вывода типов и при применении параметров функций по умолчанию, появившихся в ES6, в распоряжении разработчика оказываются подсказки, весьма напоминающие те, которые доступны при работе над TypeScript-кодом с аннотациями типов.


Пример автозавершения обычного JS-кода с выводом типов

Честно говоря, если вы используете для предоставления подсказок по типам параметры по умолчанию, то вам совершенно не нужно делать аннотации TypeScript-кода. Это — отличный приём, позволяющий сократить количество вспомогательных синтаксических конструкций, которые являются одним из минусов TypeScript.

Инструменты, используемые при написании TypeScript-кода, пожалуй, немного лучше, они выглядят более целостно, но всего этого недостаточно для того, чтобы можно было бы поставить TypeScript гораздо более высокую оценку и перекрыть недостатки этого языка.

▍Документирование API (API Documentation)


Ещё одно серьёзное преимущество TypeScript — это более качественное документирование API. Фактически, можно говорить о том, что документация к API всегда соответствует состоянию исходного кода. Документацию можно даже генерировать на основании TypeScript-кода. По этому показателю TypeScript тоже можно было бы поставить более высокую оценку — если бы, программируя на JavaScript, нельзя было бы пользоваться чем-то вроде JSDoc, Tern.js и множеством средств для генерирования документации. Лично я — не фанат JSDoc, поэтому TypeScript в моём анализе по этому показателю получает достаточно высокую оценку.

Тут надо отметить, что, даже используя лучшую в мире встроенную в код документацию, нельзя обойтись без настоящей документации, поэтому справедливо говорить о том, что возможности TypeScript скорее расширяют существующие возможности составления документации, а не заменяют их.

▍Типобезопасность (Type Safety)


При сравнении типобезопасности TS и JS, как оказалось, особой разницы выявить не удаётся. Сторонники TypeScript часто говорят о преимуществах типобезопасности, но нельзя сказать, чтобы типобезопасность значительно снижала плотность ошибок в продакшне. Это важный момент, так как применение ревью кода и TDD оказывает серьёзнейшее воздействие на устранение ошибок (одно лишь применение методики TDD приводит к снижению ошибок на 40-80%). Если совместить TDD с анализом архитектуры проектов, с проверкой спецификаций и с ревью кода, можно выйти на более чем 90% сокращение плотности ошибок. Многие из этих техник (в частности, TDD) способны помочь в нахождении тех же ошибок, которые можно обнаружить средствами TypeScript, а также многих ошибок, которые TypeScript обнаружить не в состоянии.

Здесь мы приведём некоторые выкладки из этого исследования. Теоретический максимум «общедоступных» ошибок, которые можно обнаружить средствами TypeScript — это около 15%. «Общедоступные» ошибки — это такие ошибки, которые пережили фазу разработки проекта и попали в общедоступный репозиторий.

В вышеупомянутом исследовании осуществлялось наблюдение за ошибками, о которых было известно заранее. Сюда входило и знание того, какие строки кода были изменены для исправления ошибок, в то время как проблема и её потенциальное решение были известны до типизации кода. Это означает, что даже знание о существовании ошибок не позволило, средствами TypeScript, обнаружить 85% «общедоступных» ошибок.

Почему же TypeScript не в состоянии обнаружить так много ошибок? Почему я говорю о том, что 15% обнаруженных ошибок — это теоретический максимум TypeScript? Для начала стоит отметить, что, в соответствии с рассматриваемым исследованием, ошибки в спецификациях приводят к возникновению примерно 78% ошибок в общедоступных GitHub-репозиториях. Невозможность чётко сформулировать спецификации программ или невозможность правильно реализовать спецификации ведут к самому распространённому типу ошибок. Это автоматически приводит к тому, что большую часть ошибок в программных проектах TypeScript не может выявить или предотвратить. Авторы исследования, кроме прочего, идентифицирую и классифицируют ошибки, не детектируемые средствами TypeScript. Вот гистограмма со сведениями о таких ошибках.


Ошибки, которые не детектируются средствами TypeScript

Пример «StringError» — это ошибка, которая возникает в том случае, если там, где нужна строка, используется строка, то есть ошибки в типах не возникает, но ошибку вызывает само содержимое этой строки (например — там может быть неправильный URL). Средствами статического анализа можно выявить некоторые из подобных ошибок, исследуя содержимое строк и используя описания этого содержимого. Но это даст лишь перспективу исправления небольшой доли от небольшого процента ошибок. В результате мы и говорим о том, что средствами TypeScript вряд ли когда-либо можно будет выявлять больше 15-18% ошибок.

Тут может показаться, что 15% — это уже довольно много. Почему TypeScript не может обнаружить значительно больший процент ошибок?

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

Предположим, что ваш проект содержал бы 1000 ошибок в том случае, если бы вы не применяли никаких мер по борьбе с ошибками. После того, как проект был как следует проверен, потенциальное количество ошибок, способных дойти до продакшна, сократилось до 100. Теперь, чтобы увидеть реальные возможности TypeScript, посмотрим на то, сколько из этих ошибок можно выявить с его помощью. Так как около 80% ошибок средствами TypeScript выявить нельзя, и учитывая то, что, в теории, все ошибки, выявляемые с помощью TypeScript, можно обнаружить и другими средствами, вроде использования методологии TDD, мы, поступив довольно щедро, предположим, что TypeScript выявит ещё 8% ошибок. Тут мы, кроме того, исходим из предположения, в соответствии с которым примерно половину ошибок, которые выявляет TypeScript, другими способами мы не обнаружили. В результате получается следующее:

  • Проект, в котором меры по борьбе с ошибками не применяются, содержит 1000 ошибок.
  • При использовании мер по борьбе с ошибками, не связанных с TypeScript, удалось выявить 900 ошибок.
  • После проверки проекта средствами TypeScript осталось 92 ошибки. Это значит, что благодаря внедрению TypeScript удалось обнаружить ещё 8 ошибок.


Ошибки в проекте без проверок, ошибки, оставшиеся после выполнения ревью кода и после применения TDD, и ошибки, которые остались после проверки проекта средствами TypeScript

Кто-то может не согласиться с этими выводами, говоря, что при использовании статической системы типов не нужно писать огромное количество тестов. Но подобные аргументы не выдерживают никакой критики. TypeScript не заменяет другие средства борьбы с ошибками. Даже если в некоем проекте используется TypeScript, без других мер по поиску ошибок всё равно не обойтись.


Ошибки, выявленные TypeScript и другими способами

Предположим, что средствами TypeScript было выявлено 15% от исходного количества ошибок вышеописанного гипотетического проекта. То есть — 150 из 1000. Но даже при таком подходе, если не учитывать ошибки, найденные TypeScript, другие средства поиска ошибок позволят найти 900 ошибок. Это ведёт к очевидности того факта, что, при выборе средств для борьбы с ошибками, речь не идёт о выборе TypeScript или чего-то ещё. Для поиска ошибок можно взять и TypeScript и другие средства, что, как показано выше, приведёт к обнаружению 908 ошибок из 1000 (напомним, что на эту цифру мы вышли, исходя из предположения о том, что другие средства поиска ошибок выявляют множество ошибок, которые можно обнаружить средствами TypeScript).

Мне приходилось реализовывать системы управления качеством в крупномасштабных проектах стоимостью многие миллионы долларов. Я могу сказать, что мои ожидания относительно эффективности подобных систем находятся в районе 30-80% уменьшения ошибок. Похожие цифры можно найти в следующих работах:

  • Проверки архитектуры проекта и спецификаций способны привести к устранению до 80% ошибок.
  • Применение TDD способно снизить число оставшихся ошибок на 40-80%.
  • Час, потраченный на ревью кода, экономит 33 часа поддержки проекта.

Оказывается, что ошибки, связанные с типами данных, представляют собой лишь небольшое подмножество общего количества возможных ошибок, и, при этом, существуют способы поиска таких ошибок, отличные от использования TypeScript. Всё это позволяет сделать предельно ясный вывод: применение TypeScript не способно спасти проект от ошибок. В лучшем случае его использование позволит лишь слегка сократить их число, и при этом без других мер по борьбе с ошибками обойтись не удастся. Корректность использования типов не гарантирует правильность работы программы.

На самом деле, возникает такое ощущение, будто ни инструменты разработчиков ни типобезопасность не жили по-настоящему до бума TypeScript. Но инструменты и контроль типов не могут быть единственными сильными сторонами TypeScript, правда?

▍Новые возможности JavaScript и кросс-браузерная компиляция кода (New JS Features, Compile to Cross-Browser JS)


По обсуждаемой паре показателей TypeScript получает оценку 0, что уравнивает его с JavaScript. Дело в том, что Babel обеспечивает поддержку новейших возможностей JavaScript и выполняет компиляцию кода, в котором используются современные конструкции, в код, который можно выполнять в существующих браузерах.

Со следующих показателей начинается обсуждение недостатков TypeScript в сравнении с JavaScript. Не знаю как вы, но я чувствую лёгкое разочарование. Если при разработке на чистом JavaScript можно пользоваться подсказками о типах, автозавершением и отличными средствами для поиска ошибок, тогда у нас остаётся единственный вопрос, который заключается в том, стоят ли сильные стороны TypeScript тех усилий, которые нужно приложить для использования этого языка. Для того чтобы найти ответ на этот вопрос, нам нужно пристальнее вглядеться в те показатели, по которым TypeScript получил оценки со знаком «минус».

▍Поиск разработчиков (Recruiting)


Примерно половина из тех, кто участвовал в исследовании State of JavaScript, уже использовали TypeScript и планируют пользоваться им в будущем, при этом ещё 33.7% респондентов хотят изучить TypeScript. Но 5.4% пробовали TS и говорят о том, что снова им пользоваться не будут, а 13.7% заявляют о том, что не заинтересованы в изучении этого языка. Всё это уменьшает рынок предложения труда TS-разработчиков почти на 20%, что может оказать серьёзное влияние на проекты, которым нужны большие команды программистов. Поиск работников — дорогой процесс, который может занимать многие месяцы и мешать продуктивной работе уже нанятых программистов (которые, чаще всего, являются наиболее квалифицированными представителями компаний, способными оценить навыки кандидатов на рабочие места).

С другой стороны, если вам нужно нанять одного-двух разработчиков, то использование TypeScript может сделать ваше предложение более привлекательным для почти половины возможных соискателей. Маленький проект даже может от этого немного выиграть. Если же речь идёт о командах размером в сотни или тысячи разработчиков, то такая ситуация на рынке труда способна привести к негативному влиянию выбора TypeScript на такие проекты.

▍Подготовка к работе, начальное обучение (Setup, Initial Training)


Эти мероприятия выполняются лишь однажды, поэтому их стоимость сравнительно низка. Команды, уже знакомые с JavaScript, обычно выходят на высокую продуктивность TypeScript-разработки за 2-3 месяца, а за 6-8 месяцев выходят на очень высокий уровень владения языком. Это, конечно, дороже чем взять на работу готового специалиста, но, определённо, если бы все сложности, связанные с использованием TypeScript, этим бы и ограничивались, на это можно было бы пойти без особых раздумий.

▍Отсутствующие возможности (Missing Features)


Речь идёт о функциях высшего порядка, о композиции, о дженериках с типами высших родов и о прочем подобном. TypeScript не полностью совместим с идиоматическим JavaScript. Именно в этой сфере обнаруживается моя основная проблема с TypeScript и основной источник затрат времени, сил и средств на работу с этим языком. Дело в том, что знающий JavaScript-разработчик часто будет встречаться с ситуациями, в которых сложно или невозможно использовать типизацию, но при этом добросовестный разработчик постарается сделать всё как следует. В результате такой разработчик будет многие часы тратить на поиск подходящих примеров в интернете, пытаясь узнать о том, как типизировать то, что средствами TypeScript просто невозможно нормально типизировать.

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

▍Непрерывное обучение (Ongoing Mentorship)


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

Например, новые TypeScript-разработчики обычно тяготеют к чрезмерному использованию аннотаций и встроенных в код описаний типов, в то время как более опытные разработчики стремятся к повторному использованию интерфейсов и к созданию описаний типов, отделённых от остального кода для того, чтобы избавиться от синтаксического беспорядка, который вызывают встроенные в код аннотации типов. Более опытные разработчики, кроме того, стремятся дорабатывать типы таким образом, чтобы, во время компиляции, получать более качественные сообщения об ошибках.

Повышенное внимание к типизации постоянно отнимает время разработчиков. Нечто подобное можно наблюдать при приёме в команду нового программиста. Но это выражается и в том, что опытные TypeScript-разработчики, обнаружившие что-то полезное, делятся этим с командой. Это «непрерывное обучение» — всего лишь нормальный побочный эффект коллективной работы над проектом, и это здоровая привычка, которая позволяет экономить средства в долгосрочной перспективе. Но подобные вещи выливаются в затраты времени и сил, а значит — и в затраты в денежном выражении, а TypeScript лишь увеличивает подобные затраты.

▍Дополнительная нагрузка на программистов, связанная с типизацией (Typing Overhead)


В этот показатель я включаю ту дополнительную нагрузку на программистов, которую создаёт необходимость типизации сущностей, а также необходимость тестирования, отладки и поддержки аннотаций типов. Отладка типов — это та статья расходов на использование TypeScript, на которую нередко не обращают внимания. Аннотации типов подвержены собственным ошибкам. Типизация может быть слишком строгой, слишком свободной, или попросту неправильной.

С тех пор, как я впервые столкнулся с этой проблемой, она стала куда менее серьёзной. Многие библиотеки, используемые в программных проектах, теперь оснащены информацией о типах, поэтому программистам не приходится тратить слишком много времени на исследование подобных библиотек сторонних разработчиков и на самостоятельное создание типов для них. Однако многие из подобных описаний типов всё ещё работают неправильно, во многих пакетах, за исключением самых популярных, они могут быть устаревшими.

Поэтому программистам приходится самостоятельно возиться со сторонними библиотеками, для работы с которыми им нужны сведения о типах. Часто разработчики пытаются повлиять на то, чтобы информация о типизации поддерживалась бы в используемых ими библиотеках в актуальном состоянии, делается это разными способами и с разными результатами.

Кроме того, можно заметить заметно возрастающий при использовании TypeScript «синтаксический шум». В языках наподобие Haskell типизация обычно представлена короткой однострочной конструкцией, находящейся над определяемой функцией. В TypeScript, особенно для дженериков, информация о типизации часто вторгается в код объявления функции, и, по умолчанию, представляет собой встроенные конструкции.

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

«Синтаксический шум» представляет собой проблему по нескольким причинам. Код стремятся поддерживать в чистоте по тем же причинам, по которым стремятся поддерживать в чистоте жилища.

  • Если в коде много вспомогательных конструкций — там будет больше мест, в которых могут скрываться ошибки. Значит — в коде будет больше ошибок.
  • Большое количество вспомогательных конструкций означает, что в коде становится сложнее искать то, что нужно.

Весь этот «синтаксический шум» похож на статические помехи в плохо настроенном радиоприёмнике — там больше шума, чем полезного сигнала. Избавление от «синтаксического шума» похоже на настройку радиоприёмника на нужную волну — так легче становится слышать осмысленные звуки.

«Синтаксический шум» — одна из главных проблем TypeScript. Его можно уменьшить следующими способами:

  • Улучшение поддержки дженериков с использованием типов высших родов. Это позволит избавиться от некоторых «шумов» шаблонного кода (для того чтобы лучше это понять — взгляните на систему типов Haskell).
  • Поддержка использования, по умолчанию, отдельных, а не встроенных описаний типов. Если стандартом в области TypeScript-разработки станет стремление к тому, чтобы обходиться без встроенных описаний типов, тогда синтаксис типизации будет изолирован от реализации функций, что облегчит и восприятие сигнатур типов, и их реализаций, так как они не будут друг с другом смешиваться, соперничая за внимание программиста. Внедрить подобное можно, тщательно пересмотрев документацию, этому может поспособствовать и соответствующий настрой опытных TypeScript-разработчиков, отвечающих на вопросы на Stack Overflow.

Итоги


Мне всё ещё многое нравится в TypeScript, и я всё ещё надеюсь, что этот язык станет лучше. Некоторые из тех проблем, о которых тут шла речь, могут быть решены путём добавления в язык новых возможностей или путём улучшения документации.

Однако нам не следует закрывать на эти проблемы глаза, а сторонники TypeScript будут вести себя безответственно, если станут превозносить преимущества этого языка, ничего не говоря о его недостатках.

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

Я надеюсь, что по мере роста TypeScript многие из тех, кто пишет на этом языке, пройдут стадию «медового месяца» и поймут истинную цену использования TypeScript и его ограничения. При этом, чем обширнее будет TypeScript-сообщество, тем больше умных людей подключится к решению проблем этого языка.

Я определённо будут пользоваться TypeScript, в том состоянии, в котором он находится сейчас, при разработке небольших опенсорсных проектов, в основном — для того, чтобы облегчить жизнь других программистов, пишущих на TypeScript. Но я не буду применять текущую версию TypeScript в моём следующем крупномасштабном проекте. Всё дело в том, что чем больше будет проект — тем дороже, во всех смыслах, будет для него использование TypeScript.

Закончу на иронической ноте. На официальном сайте TypeScript говорится о том, что перед нами «JavaScript, который масштабируется». Честнее было бы добавить к этому слогану ещё одно слово и сделать его таким: «JavaScript, который плохо масштабируется».

Уважаемые читатели! Просим вас поделиться впечатлениями о TypeScript.

RUVDS.com
930,00
RUVDS – хостинг VDS/VPS серверов
Поделиться публикацией

Комментарии 52

    0
    Мне кажется автор немного торопится говоря о 2019 как бы в прошедшем времени и утверждая про «не будет выбора», тем более, что если в начале он говорит про нет выбора а завершает про «But I will not use the current version of TypeScript in my next large scale application, because the larger the project is, the more the costs of using TypeScript compound.»
      +7
      В результате такой разработчик будет многие часы тратить на поиск подходящих примеров в интернете, пытаясь узнать о том, как типизировать то, что средствами TypeScript просто невозможно нормально типизировать

      Недостаток TS в том, что он не JS :) Фиерично. То, что программист не может типизировать свой код означает, что программист написал плохо. Плохой программист, плохой. *бьет программиста газетой*

      Анализ начинается с:
      следует хорошо понять то, с чем именно я сравниваю TypeScript. Это не «просто JavaScript», а JavaScript и инструменты, созданные для эффективной разработки на этом языке.


      А потом идёт сравнение с воображаемым «идеальным» ЯП в котором все баги видны, программисты его знают с рождения, а код не содержит синтаксического шума. Если не догадались, то автор сравнивает с LISP.

      Пример:
      Отсутствующие возможности (Missing Features)
      Речь идёт о функциях высшего порядка, о композиции, о дженериках с типами высших родов и о прочем подобном.

      Не помню этих фич в JS. И далее аналогично «хотелки» сравниваются с возможностями TS.
        +1
        То, что программист не может типизировать свой код означает, что программист написал плохо.

        Разница в «не может типизировать свой код» и «не может типизировать свой код средствами TypeScript» огромна. Последний не поддерживает статические методы в классах, нормальное наследование и полноценные дженерики. Любая функциональная библиотека будет недотипизирована и проблема тут как раз в отсутствии полноценной системы типов в TypeScript
          0
          А «полноценные дженерики» они в каком языке есть? В C#? :)
        0
        Можно ли начинать учить ts в обход js?
          +6
          Начать можно, но в процессе неизбежно вылезут артефакты предка, поэтому общее представление лучше все же иметь.
            0
            Спасибо за ответ!
          +4

          Вы же знаете, что Eric Elliott знатный тролль и набрасывать, да?)

          +5
          После проверки проекта средствами TypeScript осталось 92 ошибки. Это значит, что благодаря внедрению TypeScript удалось обнаружить ещё 8 ошибок.

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


          Правильная последовательность — с самого начала использовать статическую типизацию.

            +4

            Беда только в том, что TypeScript очень плох в плане типизации и часто ошибается.


            Например, вот из свежего:


            https://github.com/Microsoft/TypeScript/issues/29530


            // ./lib.ts
            export type Foo<T extends string> = { foo: T }
            
            // ./index.ts
            type Foo<T> = import('./lib').Foo<T>;
            // Should require matching constraint:
            // type Foo<T extends string> = import('./lib').Foo<T>;

            https://github.com/Microsoft/TypeScript/issues/29509


            import React from 'react';
            
            const myHoc = <ComposedComponentProps extends any>(
                ComposedComponent: React.ComponentClass<ComposedComponentProps>,
            ) => {
                type WrapperComponentProps = ComposedComponentProps & { myProp: string };
                declare const WrapperComponent: React.ComponentClass<WrapperComponentProps>;
            
                declare const props: ComposedComponentProps;
            
                // Expected no error, got none - good
                <WrapperComponent {...props} myProp={'1000000'} />;
                // Expected error, but got none - bad!
                <WrapperComponent {...props} myProp={1000000} />;
            };

            https://github.com/Microsoft/TypeScript/issues/29409


            const f: () => void = (a = '') => isFinite(a); // should be error

            Тысячи их...


            На самом деле очень сложно полагаться на такую бажную типизацию. Компилятор говорит тебе, что всё хорошо, а потом ты ловишь TypeError в рантайме. Компилятор начинает ругаться на корректный код, и ты начинаешь расставлять as any, чтобы только лишь заткнуть его.

              –1

              Ну да, если писать as any для того чтобы "заткнуть" тайпчекер — то проще изначально писать на Javascript и не выдумывать.

                +4

                Зачем вы передёргиваете? Я говорю о случае, когда типизация корректна, но компилятор считает, что это не так:


                import * as React from 'react';
                import { connect } from 'react-redux';
                
                interface TestCmpProps {
                  text: string;
                }
                
                class TestCmp extends React.Component<TestCmpProps> {
                  render() {
                    return (
                      <div>{this.props.text}</div>
                    );
                  }
                }
                
                // const TestCmp = (props: TestCmpProps) => (
                //   <div>{props.text}</div>
                // );
                
                const mapStateToProps = state => ({
                  text: state.text
                });
                
                export default connect(mapStateToProps)(TestCmp);

                Ошибка
                Error:(22, 41) TS2345: Argument of type 'typeof TestCmp' is not assignable to parameter of type 'ComponentType<never>'.
                  Type 'typeof TestCmp' is not assignable to type 'ComponentClass<never, any>'.
                    Types of property 'contextType' are incompatible.
                      Type 'React.Context<any>' is not assignable to type 'import(".../node_modules/@types/react/index").Context<any>'.
                        Types of property 'Provider' are incompatible.
                          Type 'React.ProviderExoticComponent<React.ProviderProps<any>>' is not assignable to type 'import(".../node_modules/@types/react/index").ProviderExoticComponent<import(".../node_modules/@types/react/index").ProviderProps<any>>'.
                            Types of property 'propTypes' are incompatible.
                              Type 'WeakValidationMap<ProviderProps<any>>' is not assignable to type 'ValidationMap<ProviderProps<any>>'.
                                Property 'value' is optional in type 'WeakValidationMap<ProviderProps<any>>' but required in type 'ValidationMap<ProviderProps<any>>'.

                В этом примере или писать TestCmp as any, или безуспешно пытаться обосновать компилятору его заблуждения относительно типов.

                  0
                  Здесь нужно каким-то образом указать компилятору тип для state. Или поправить тайпинги для react-redux.
                    +5

                    Даже такой вариант ничего не меняет:


                    interface AppState {
                      text: string;
                    }
                    
                    const mapStateToProps = (state: AppState): TestCmpProps => ({
                      text: state.text
                    });

                    Идея поправить тайпинги для react-redux, конечно, замечательная. Но они весьма нетривиальны, а TypeScript не предоставляет никакого удобства в их отладке, на любой чих выплёвывая ошибки в стиле C++ как выше.

                      0
                      так-то это вполне валидный вариант. что здесь не так?
                        0

                        У вас компилируется?

                          0
                          я вставил это пример в свой проект. и никаких ошибок, всё ок
                        +2
                        А Вы пробовали скормить этот пример Flowtype? Он выводит типы?
                        Мне кажется, тут проблема не в TypeScript как таковом. А в том что разрабы из Facebook пишут React на Flow. И типизация для TypeScript делается по остаточному принципу.
                          +1
                          Типизация для TypeScript делается не то чтобы по остаточному принципу, а вовсе другими людьми…
                            +1
                            И в этом огромная пробелема. Лучше выбрать пускай даже менее функциональное решение, но изначально написанное на TypeScript, чем использовать сторонние файлы деклараций.

                            Даже если файлы декларации пишут сами авторы JS библиотеки, что случается не часто, это далеко не всегда гарантирует их полноценность и валидность.
              0
              А что делает CMake в данных по росту языков?
                0
                У него есть свой язык, который вполне себе полон по Тьюрингу.

                Кмк, приведенная статистика — сравнение технологий самих с собой, сказывается тренд переезда C++-проектов на CMake. Тот же Qt собирается переключиться на него, хороня свои QMake и Qbs.
                  0
                  На мой взгляд не совсем корректный рейтинг.

                  Тот же Qt собирается переключиться на него, хороня свои QMake и Qbs.

                  Надо же, все возвращается к истокам.
                  Последний раз когда имел с ним дело именно CMake собирал проект, а Qbs был еще в зачаточном состоянии ))
                +1
                Интересно, какие именно случаи нельзя типизировать на текущиймомент? Было такое, но где-то спару версий назад все, врде бы, решено. Разве нет?

                И да, бывает так сложно, что время затрачивается всотни раз больше. Например на js участок кода можно написать за минуту, а на ts день-два уйдет. Это при условии, что создаваемый код является описанием какого-то собственного архитектурного решения. То есть такая проработка очень редко требуется при работе с библиотеками или фраймворками. А вот при их написании она необходима. И с этим нужно смерится вне зависимости от потрачего времени. Ведь всем нравится умный автокомплит восста процентах работы с библиотекой. Ведь это экономит время и деньги и самое главное — нервы. Легче будет только если код будет писать ИИ.

                И странное, что в 2019 году trypescript ещё не все используют. js, если будет долго жить, то станет ts.
                  +3

                  mongoose например нельзя нормально типизировать, если модели используют methods и statics.
                  Гвоздями типы прибить везде можно, но искоробки тайпинги не годятся. Решительно не хватает в языке нормальных примесей и селфтайпов.

                    –1
                    Если бы штуковина mongoose изначально проектировалась и писалась на trypescript, то я думаю что удалось бы типизировать. Бывает проще переписать всю библиотеку на trypescript, чем написать полноценные и небажные декларации и «чудо-js-коду».
                      +2

                      Спору нет — все так и есть. Вопрос был про штуки, которые нельзя типизировать. Я привел пример достаточно популярной библиотеки. И даже сказал как решить, но у примесей в ТС сложная судьба.

                        +3
                        Полностью с Вами согласен. Типизация, это прежде всего — ограничение. Это ограничение призвано не только не позволить допустить ошибку связанную с совместимостью типов, но и дать программе выйте из архитектурной колии. Ограничения в виде типизации не позволят сложить яйца в один мешок с картошкой, что пощряет javascript. Поэтому, да, не просто написать правильную декларацию для кода на js, который был спроектирован не в типизированном стиле. Для этого придется с нуля продумывать независимую от библиотеки архитектуру и каждый раз подгонять её под javascript код. А этим мало кому хочется заниматься. Но всеже кривые декларации во много раз лучше чем вовсе никакие. Без автокомплита в 2019 просто жуть. Невозможно все держать все api в голове, когда ты пишешь на огромном множестве языков моножестов лет. Все в кашу превращается и спасает только автокомплит и автодокументированние в виде деклараций.
                      0

                      Один из насущных примеров это генераторы.

                        0
                        Есть (по крайней мере были в версии 2.7) вроде тривиальные случаи, которые сложно типизировать. Например, (обобщенные кажется) статические фабричные методы с наследованием. Почему-то this у них не объект этого класса и нельзя просто взять и указать, что это он.
                        +1
                        Честно говоря, если вы используете для предоставления подсказок по типам параметры по умолчанию, то вам совершенно не нужно делать аннотации TypeScript-кода.

                        Вот это особенно весело. А что нам делать, если контракт функции не предусматривает параметров по умолчанию?


                        Если уж так хочется — можно использовать TypeScript как инструмент, а не как язык (--checkJs). И все гипотетические проблемы вроде Typing Overhead уйдут.

                          +2
                          Есть подозрение что товарищь Eric Elliott никогда не писал что-то сложнее «одноразового кода, стиля — один раз запустил и на помойку».
                          Типизация может быть слишком строгой, слишком свободной, или попросту неправильной.
                          Неправильной типизация может быть когда сам код написан на JavaScript, а декларация подключется отдельно. Очень частый случай когда при таком подходе вылазят грабли. Поэтому всегда лучше искать решения изначально написанные на TypeScript, желательно с включенной strict опцией компиляции.

                          Следующая цитата из его опуса как раз является преимуществом, а не недостатком. То есть один раз описал модель данных и все, больше не нужно постоянно при обращении к коду думать что там за данные такие могут быть и аргументы какого типа, не нужно все держать в голове, можно ведь просто выразить все в однозначном виде в коде. Недостатком это может быть только в случае ондоразовых проектов которыми полагаю Eric Elliott увлекается, но тогда и TypeScript не нужно брать вообще. Для программистов описание типов это не нагрузка, а наоборот облегчение в перспективе. Нагрузкой это может быть для мартышек.

                          Дополнительная нагрузка на программистов, связанная с типизацией (Typing Overhead)

                          В этот показатель я включаю ту дополнительную нагрузку на программистов, которую создаёт необходимость типизации сущностей, а также необходимость тестирования, отладки и поддержки аннотаций типов. Отладка типов — это та статья расходов на использование TypeScript, на которую нередко не обращают внимания. Аннотации типов подвержены собственным ошибкам. Типизация может быть слишком строгой, слишком свободной, или попросту неправильной.

                            –11

                            Может, это Typescript нужен лишь мартышкам, неспособным писать без поддерживающего их код каркаса?)

                              +5
                              Почему-то многие забывают, что код мало написать. Его еще нужно читать, поддерживать и рефакторить. Для этого и предназначен каркас из типов.

                              Простейший пример: найти все использования поля User.name (но не {еще что-то}.name) и переименовать это поле. И как такое автоматизировать без покрытия типами?

                              А так-то налабать проектик на пару-тройку тысяч строк всегда проще на голом JS.
                                –6
                                А как вы, интересно, автоматизируете те ситуации, когда написано не `User.name`, а `User[«name»]` или `let field=«name»; User[field]`? Когда название поля или метода возвращается из функции? Когда экземпляр отправляется аргументом в функцию и там у него что-то вызывается, в зависимости от фазы луны, клиентского запроса или значения в бд?

                                Ответ — никак. Покрывать функционал тестами и проверять, что после рефакторинга они не упали.
                                  +4

                                  В typescript для этого есть keyof

                                    0

                                    Я не слишком в ts разбираюсь, поэтому вопрос. Этот keyof позволит заменить все вхождения User.name на User.firstName "одной кнопкой", вне зависимости от того, как это реализовано — вызовом метода напрямую, использованием переменной с названием метода как ключ хеша, и тд?


                                    Мне вот кажется, что на такой анализ ИДЕшки не способны. Может конечно, я в прошлом застрял — ничем сложнее саблайма или атома не пользуюсь уже давно.

                                      0

                                      Не совсем. При компиляции вы точно получите ошибку, а авто-ренейм пока не реализован скорее специально, но его можно реализовать. Это конечно же доступно, только если вы не балуетесь форсированными кастами.

                                        0

                                        Понятно. То есть он просто не даёт использовать отдельные возможности языка.


                                        Ладно, это все дело вкуса, полагаю. Мне лично не доводилось писать огромный энтерпрайз на миллионы строк, на каком-нибудь angular. Так что из сложностей с отсутствием типов не возникало.


                                        Вообще, по мне, на фронте сложное — это интерфейсы. Их состояния и их вёрстка. Делая какой-нибудь аналог экселя в браузере, заколебешься с двумя вещами — чтобы одна часть состояния не влияла на другую (что по большей части решает либа для реактивного интерфейса), и чтобы браузер нормально отрисовывал десятки тысяч элементов, которые ведут себя по-разному, но должны быть единым целым (тот же эксель примером — какие-то колонки должны быть фиксированными, какие-то прокручиваться, какие-то прокручиваться в одну сторону и быть фиксированными в другой, и тд) и при этом не лагать от избытка логики. Типизация тут — от силы пара процентов от всех проблем, вроде статической погрешности.


                                        Вот на беке да, допускаю что ts очень полезен может быть.

                                          +2

                                          Нет, он даёт использовать. Просто авторенейма нет

                                            +1
                                            энтерпрайз на миллионы строк, на каком-нибудь angular.

                                            Потребность в типах зависит не только от размера кода. Типы всегда есть. Просто они либо записаны в виде TypeScript / FlowType /JSDoc / JSON Schema / Mongoose / Normalizr / etc. Либо они живут у вас в голове.


                                            И когда вы являетесь автором этого куска кода, вам все кажется очевидным. Вы находитесь в контексте задачи, и загрузили в свою "оперативную память" какую-то ее модель. И вам кажется, что типы — это лишний "шум". Но для вашего коллеги это не так. Как впрочем и для вас самого через год.


                                            С этой точки зрения TypeScript — это всего лишь принцип "Explicit is better than implicit".


                                            Вообще, по мне, на фронте сложное — это интерфейсы. Их состояния и их вёрстка.

                                            Зависит от предметной области. Если у вас CRUD или сайт строится вокруг контента — то да. А если, например, совместное редактирование в реальном времени — то на первый план выходят алгоритмы и структуры данных.

                                              0
                                              > С этой точки зрения TypeScript — это всего лишь принцип «Explicit is better than implicit».

                                              Но средства сделать явным то, что в JS неявно ограничены, не покрывают или покрывают с большим трудом и оверхедом возможности JS
                                                0
                                                Да, к сожалению это так. Но я не вижу особых вариантов для разработчиков TypeScript. Ведь они не могут взять и спроектировать систему типов с нуля. А вынуждены находить какие-то распространенные паттерны в программах на JS и прикручивать к ним типизацию. А учитывая бурное развитие JS в последние годы — нелегкая это задача. Но и на том спасибо.
                                +2
                                Эрик Эллиот часто пишет очень спорные и иногда абсурдные, категоричные, а то и даже глупые вещи под видом непреложной истины
                                0

                                Как много воды, хоть кто-то прочитал полностью?

                                  0
                                  Как ни странно, но сейчас мне TypeScript приносит больше при работе в ФП стиле, а в ООП как-то хватает автовывода стилей от JetBrains
                                    0

                                    Статический анализ TS — это классно, я его активно использую, это то, что мне реально помогает в работе. Но вот забавная штука: для этого вовсе не обязательно писать на TS.

                                      –1
                                      Тогда вроде лучше flow использовать. Говорят его система выводов типа сильнее, а объявления типов можно делать в doc комментариях.
                                        0
                                        Если сравнивать jsdoc-комментарии и указание типов в Typescript, то комментарий занимает больше места и писать его сложнее.
                                          0
                                          Компенсируется (вернее может компенсироваться — сам не проверял) более мощной системой вывода типов flow из-за чего необходимость в явном указании падает.
                                            0
                                            Поддержка jsdoc на уровне редактора вполне спасает от лишних телодвижений. Конечно многое зависит от принятых в команде конвенций, но бесконечные декларации интерфейсов в TS — вещь тоже не самая компактная и простая. И, в отличие от синтаксиса основанного на комментах — она сильно видоизменяет (утяжеляет визуально логическую часть) сам код. А вот возможность дебага кода напрямую в браузере без возни с сорсмапами — бесценна. Поэтому я выбираю стат-анализ от TS + современный JS + JSDOC.

                                      Только полноправные пользователи могут оставлять комментарии. Войдите, пожалуйста.

                                      Самое читаемое