Контекст: Turbo — это как htmx, т.е. с идеей передачи html между бэкендом и фронтендом и управлением состоянием на бэкенде, но от создателя Basecamp (сервиса менеджмента проектов), HEY (email-сервиса) и фреймворка Ruby on Rails.
прим. перевод.

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

Дело в том, что на самом деле мне очень нравится JavaScript. Я бы даже сказал, что это мой второй любимый язык после Ruby. Да, с большим отрывом, но всё же второй. Хотя так было не всегда. Но после того, как в JavaScript появились полноценные классы, а также все остальные улучшения после ES6, писать на нём стало по-настоящему приятно.

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

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

Однако это не призыв переубедить кого-либо в чём-либо. Как я уже говорил в статье «Типы и образы мышления в программировании», очень немногие программисты обычно заинтересованы в том, чтобы их мнение о типизации изменилось. Большинство программистов в самом начале своей карьеры обнаруживают, что их либо сильно тянет к типизации, либо или не очень, а затем проводят остаток карьеры, рационализируя "правильный выбор" для себя и других.

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

Это также необходимо. Потому что в отличие от таких языков, как Ruby, которые являются языками по выбору, когда речь идёт о серверной части, JavaScript — это язык необходимости (если не учитывать WebAssembly, прим. перевод.), когда речь идёт о клиентской части. Хотя вы можете компилировать его используя различные диалекты (TypeScript, Elm, ClojureScript, ReScript, и т.д., прим. перевод.), вам всё равно придётся признать тот факт, что выполнение кода в браузере означает выполнение JavaScript. Поэтому возможность писать на нём, не прибегая к дополнительным инструментам и не используя сильную типизацию, является благословением в сложившихся обстоятельствах.

Что же, прощай, TypeScript. Пусть ты принесешь много строгости и удовлетворения своему племени, позволяя остальным наслаждаться JavaScript в том славном духе, в котором он был изначально задуман: Свободным от сильной (строгой) типизации.


Можно о типизации думать разное, но хотя бы файлики .d.ts с описанием типов, или же аннотации JSDoc можно было бы внедрить — чтобы облегчить ношу пользователей библиотеки и, тем более, контрибьюторов в неё. А уж зачем было выкидывать Prettier (инструмент для авто-форматирования), непонятно :)

В дополнение к переводу написал пост. Подписывайтесь там и тут, если ещё не. Впереди много полезного контента: как переводов, так и самостоятельных статей.

Комментарии (100)


  1. Nurked
    08.09.2023 15:17
    +10

    Если честно, лично для меня вся радость Typescript - это просто статическая проверка на этапе компиляции. Хорошо, я попытался воткнуть стрингу в номер. Ай яй яй. Нехорошо.

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

    Более того, даже самая, казалось бы нативная среда разработки для ТС - VSCode представляет собой непонятное нечто. Ошибки при компиляции представляют собой плащеницы. Мне надо минут 10 каждый раз, чтобы понять, какое поле я пропустил в каком-то типе.

    В итоге, что?

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

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

    В итоге, мне кажется, что я трачу больше времени на обслуживание компилятора Typescript и Eslint, чем на разработку ПО.


    1. novusnota Автор
      08.09.2023 15:17
      +1

      Да, многое так. Авторы библиотек часто уходят с TypeScript на JavaScript, потому что так банально проще отлаживать и копаться в исходниках, в том числе и в node_modules. Но, всё же, JSDoc и/или .d.ts пишут, потому что ловить undefined is not a function и очепятки не хочется :)


      1. Pab10
        08.09.2023 15:17
        +3

        JSDoc вполне себе достойная полумера для облегчения кодинга. Closure Compiler вроде даже умел на основе этих аннотаций делать статическую проверку. И зачем тогда эти лютейшие генерики и костыли?


    1. Nipheris
      08.09.2023 15:17
      +6

      Поднимаем JSON с диска, парсим его в тип бала, в котором у нас есть поле бла, а на диске у нас лежала стринга. Что мы получаем? Мы получаем полу-статическую типизацию.

      К сожалению это следствие того, что JSON.parse возвращает any, это легаси с тех времён, когда unknown ещё не придумали. Если б там был unknown, компилятор от вас потребовал бы :)


      1. Nurked
        08.09.2023 15:17
        +3

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

        Просто прикол в том, что если я, ни дай Боже-Бог и не искуси меня Дьявол, напишу any в своём коде, просто по приколу, чтобы выплюнуть переменную в логи и посмотреть на неё, то на меня будет сниспослано пять тысячь великих ворнингов, которые будут прикрыты ещё двумя тысячами ошибок.

        Зато, если мне в строгий тип случайно залетает что-то левое, то язык это проглатывает за милую душу, и притворяется, что ничего не происходит.

        В итоге - 80% моего кода - это проверка на undefined.


        1. DirectoriX
          08.09.2023 15:17
          +1

          Как будто в базовом JS не надо проверять на undefined...

          Да и TS не один такой, где переменную с типом, аналогичным any, надо проверять на пустое значение: в C это проверка указателей на NULL (а потом ещё и приведение к ожидаемому, а не фактическому типу), в C++ - на nullptr, в Python - проверка на None, в Go - на nil, и так далее. Даже с более мощными, полноценными алгебраическими системами типов, всё равно надо проверять Option на Some(x) / None в случае Rust или Maybe на Just x / Nothing в случае Haskell, хоть там это и зачастую удобнее, чем может предложить if.


          1. Nurked
            08.09.2023 15:17
            -3

            О, нет, я на самом деле не undefined боюсь. Благо в JS этот костыль можно сделать просто через if(variable), а в TS приходится дописывать, что ещё тебе для счастья надо.

            Я говорю о том, что вы запросто можете обнаружить string там где вы по своему типу ожидаете int. И это не вызовет никаких противоречий в среде исполнения. Эта типизация - только для статической проверки кода. Но такую уже проще сделать на самом JS.


            1. Gruzchick
              08.09.2023 15:17
              +2

              Если по логике в number может оказаться и string то тип поля надо определить как "number | string", в чём проблема?


          1. Hardcoin
            08.09.2023 15:17

            А в чем проблема maybe проверять на nothing? Это же не легаси, это фича для удобства. Если nothing не нужен, то и maybe не требуется. Используешь просто тип и ничего левого компилятор не пропустит.


            1. DirectoriX
              08.09.2023 15:17
              +1

              Проблемы нет, просто хотелось напомнить, что если переменная (точнее, её тип) допускает значение, равное "ничего", то без проверки на это самое "ничего" не обойтись, независимо от языка и строгости/мощности его системы типов.

              Кстати, очень интересно наблюдать за С-программистами, которые изучают алгебраические типы, и осознают, что type* - это фактически сумма NULL и non_null_ptr<type*>.

              P.S. Зачем в JS, в отличие от большинства других языков, есть аж два разных "ничего" ( "ничего потому что ничего" =undefined и "ничего потому что так надо" =null) - отдельный интересный разговор.


              1. Hardcoin
                08.09.2023 15:17

                допускает значение, равное "ничего", то без проверки на это самое "ничего" не обойтись

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

                Там, где по логике вам "ничего" не нужно, вы такую переменную не заводите и проверка не нужна.


      1. impwx
        08.09.2023 15:17

        Имхо, если бы JSON.parse возвращал unknown, было бы неудобно работать. По аналогии: массив может вернуть undefined при обращении по несуществующему индексу, и по-честному нужно было бы делать тип возвращаемого значения T | undefined, но проверок будет больше чем осмысленного кода.


        1. Nipheris
          08.09.2023 15:17
          +3

          noUncheckedIndexedAccess.
          Но да, это хороший аргумент. Собственно разработчики TS постоянно ищут подобный баланс в различных вещах - где например, as const появился именно потому, что по-умолчанию типы не остаются литеральными (а могли бы!) и расширяются по ряду интуитивных правил. Например, тип значения 'foobar' мог бы по-умолчанию выводиться как 'foobar', но это было бы непрактично, поэтому он расширяется до string.


    1. DarthVictor
      08.09.2023 15:17
      +5

      Поднимаем JSON с диска, парсим его в тип бала, в котором у нас есть поле бла, а на диске у нас лежала стринга. Что мы получаем? Мы получаем полу-статическую типизацию.

      Ну используйте статически типизированный парсер файлов с диска.


      1. Nurked
        08.09.2023 15:17
        +2

        А почему бы просто не взять обыкновенный JS? В данном случае, как раз автор оригинальной статьи и прав. Если там на диске такое всё кучерявое, то какой смысл писать на TS?


        1. andreymal
          08.09.2023 15:17
          +6

          Чтобы привести это самое «кучерявое» в нормальный строго типизированный вид, например? Я не очень представляю, как можно работать с данными, имеющими тип «хрен знает что там»


          1. Spaceoddity
            08.09.2023 15:17

            Забавная рекурсия получается. Вроде же TS позиционируется как лекарство как раз для "работы с этим самым кучерявым".

            Я вот не очень представляю как вместо номера может "нечаянно" прийти строка... Если я ожидаю номер - я и получу номер. Так что перманентный бардак с типами обычно как раз у адептов TS. Вначале разводим бардак с типами, а потом лечим следствие, а не проблему))


            1. andreymal
              08.09.2023 15:17
              +5

              Значит вы не работали с реальными данными в реальных проектах. Прилёт номера вместо строки - вполне обычное явление, и перед работой нужно проверить, что номер является номером, и typescript заставит это проверить (если не лепить any куда попало) - чем он и прекрасен


              1. Spaceoddity
                08.09.2023 15:17
                -5

                В 100500 раз слышу эту мантру...

                Ну т.е. вы расписываетесь в том, что в коде у вас полнейший бардак? Который вы красиво именуете "обычное явление"))

                Даже если там данные отправляет какая-то машина, живущая сама по себе, в чём проблема по дефолту приводить к строке?


                1. andreymal
                  08.09.2023 15:17
                  +7

                  "Вы просто не работали с очень крупными проектами"

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


                  1. Spaceoddity
                    08.09.2023 15:17
                    +2

                    совершенно непонятно

                    Ну вот и ответ


                    1. andreymal
                      08.09.2023 15:17
                      +5

                      Поработаете в крупных проектах без typescript - потом прибежите в эту ветку плакаться, что как же я был прав :)


                      1. Spaceoddity
                        08.09.2023 15:17
                        -3

                        Ой, там кто-то выше расстроился, что я подобную аргументацию уже предупредил? Ну мне несложно повторить))

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


                1. andreymal
                  08.09.2023 15:17
                  +1

                  что в коде у вас полнейший бардак

                  Изначально речь не о коде, а о ВНЕШНИХ данных, которые я НЕ контролирую

                  в чём проблема по дефолту приводить к строке?

                  В том, что мне нужна не строка, а число


                  1. Spaceoddity
                    08.09.2023 15:17
                    +2

                    Речь не о коде, а о ВНЕШНИХ данных, которые я НЕ контролирую

                    Это всё и есть кодовая база. Это же один проект?))

                    Вообще как это получается? На выходе бэка у вас абракадабра, на входе фронта всё разложено по полочкам? Т.е. вот это "нормальная практика"? Т.е. весь хайп вокруг TS основан на том, что бэкенд, со всеми его "строго типизированными ЯПами" не может корректно типизацию провести, а фронтенд с "динамически типизированным JS" может? Мы в этой логической цепочке ничего не перепутали? Может каждый будет заниматься своими обязанностями?

                    В том, что мне нужна не строка, а число

                    Ну приводите к числу))

                    И яснее объясняйте заодно:

                    Прилёт номера вместо строки - вполне обычное явление


                    1. andreymal
                      08.09.2023 15:17
                      +8

                      Это же один проект?))

                      Нет, сторонние компании, с которыми я обмениваюсь данными, никак не относятся к проекту (и некоторые даже не знают о существовании моего проекта)

                      На выходе бэка у вас абракадабра

                      С чего вы вообще взяли, что речь о бэке и фронте? Ещё раз, речь о ВНЕШНИХ данных, которые вообще не мои и создаются не мной

                      Ну приводите к числу))

                      "Две книги по [object Object] рублей, итого NaN рублей"? Спасибо, не надо


                      1. Spaceoddity
                        08.09.2023 15:17

                        "Две книги по [object Object] рублей, итого NaN рублей"? Спасибо, не надо

                        Как будто вам TS тут волшебным образом нужные данные подставит))


                      1. andreymal
                        08.09.2023 15:17

                        По крайней мере он хотя бы не позволит внезапно заменить число на строку:

                        let userCartSum = 0;
                        const bookPrice = "9"; // Бэкенд, бессердечная ты сволочь
                        userCartSum += bookPrice + bookPrice;  // Не "99", а не скомпилится


                      1. Spaceoddity
                        08.09.2023 15:17
                        +1

                        Если вы боитесь такой подлянки от бэка, что мешает сделать так:

                        let bookPriceNumber = Number(bookPrice)
                        if(isNaN(bookPrice)) console.warn("Алярм! Пришла какая-то лабуда вместо цены!")


                    1. andreymal
                      08.09.2023 15:17
                      +1

                      Ну а впрочем ситуацию с бэком и фронтом тоже можно рассмотреть. Вот допустим изначально с бэка прилетает информация об авторе поста в виде строки с никнеймом, но потом бэк решает добавить больше информации и меняет строку на объект с инфой (аватарка, карма и т. п.), нарушая обратную совместимость. Как, не проверяя типы по всей кодовой базе, разработчик фронта может быть уверен, что он не забыл поменять условное author на author.nickname везде где надо? Компенсировать отсутствие типов 100% покрытием тестами или есть более адекватные варианты?


                      1. Nipheris
                        08.09.2023 15:17

                        Хорошее замечание про тесты.
                        Строгость типизации - это такая прямая. С одного конца динамические языки, где именно что нужно покрывать код тестами в том числе на адекватность входа и реакцию на него. Посередине - языки вроде TS, где часть проверок корректности уезжает в compile-time. С другого конца - языки вроде Idris, где типизация настолько мощная, что код пишешь по принципу "компилируется - значит корректен". Unit-тестов ещё меньше, важнее становятся всякие e2e и интеграционные.


                      1. andreymal
                        08.09.2023 15:17

                        Хотя я сейчас понял, что продолбался с примером и от неявного преобразования объекта в строку TypeScript всё равно не спасёт:

                        type Author = { nickname: string };
                        const author: Author = { nickname: 'admin' };
                        console.log(`Автор поста - ${author}`);
                        // Автор поста - [object Object]

                        Однако обычный JavaScript от такого тоже всё равно не спасёт)

                        Впрочем, можно прикрутить какой-нибудь плагин к какому-нибудь линтеру, я надеюсь?



                      1. Spaceoddity
                        08.09.2023 15:17

                         что он не забыл поменять условное author на author.nickname везде где надо

                        Во-первых, почему бэк добавляет одну фичу в одном месте, а я должен лопатить после этого весь код?

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

                        В-третьих, вместо одной строки может прийти другая строка - TS это спокойно схавает. И уверенности в корректной работоспособности приложения вам это не прибавит. Тут надо именно понимать - что откуда куда приходит и куда уходит))


                      1. andreymal
                        08.09.2023 15:17
                        +1

                        меняя строку на объект во всех местах, где она встречается.

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

                        с поиском по всей кодовой базе

                        Опять же — искать буду не я, а TypeScript

                        вместо одной строки может прийти другая строка - TS это спокойно схавает.

                        Поэтому особо упоротые по типам идут ещё дальше и заводят по отдельному типу для каждого отдельного вида строк (и для каждого отдельного вида чисел, чтобы нельзя было случайно сложить килограммы с метрами и так далее) — но это уже другой уровень, которого лично я пока ещё не достиг


                1. Nipheris
                  08.09.2023 15:17
                  +2

                  Ну т.е. вы расписываетесь в том, что в коде у вас полнейший бардак? Который вы красиво именуете "обычное явление"))

                  Если у вас в проекте 200 человек, как может не быть бардака? Они все разные, у них разный уровень подготовки, разный опыт. Ещё они постоянно увольняются (в айтишечке же если больше двух лет работаешь на одном месте - значит всё, деградируешь. Бред кмк, но люди же так и скачут по компаниям), приходят новые. Бардака не может не быть, если за этим не следить.
                  Вот TS - и есть средство слежения. Никто не говорил, что он очень нужен в проектах, где 5 или даже 15 человек. Только как раз таки все деньги крутятся в тех компаниях, где ПО сложное, и его разрабатывает много людей.


                  1. andreymal
                    08.09.2023 15:17
                    +4

                    Никто не говорил, что он очень нужен в проектах, где 5 или даже 15 человек.

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


                    1. Nipheris
                      08.09.2023 15:17

                      А потом однажды обнаруживается, что в команде уже 200 человек, из которых никто не может ответить

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


                      1. Nurked
                        08.09.2023 15:17
                        +2

                        Я бы тут говорил о легаси системах. В коде может быть и бардак, но переписывать его не будут. Пусть стоит.

                        Но прикол вот в чём. Только что дебажил систему. Фронт на реакте с TS. Бэк на голанге. Голанг ожидает от фронта набор строк ключ-значение. Внезапно после добавления нового параметра бэк бомбит ошибками.

                        Открываю логи - смотрю. Несчастный голанг ожидал строки. А я ему в json прислал число! Тут голанг и бомбануло. Пришлось добавлять toString() на стороне морды в TS.

                        Вот такого поведения я ожидаю от строго типизированого языка. А не этих прыжков через обручь с насвистыванием гимна Америки.


                  1. Spaceoddity
                    08.09.2023 15:17

                    Реально, а чем тогда эти 200 человек заняты, что они понятия не имеют с чем они работают? Что за код они там пишут? Они же как-то должны манипулировать этими данными, а они вообще не в зуб ногой - что это за данные? Линтер ублажают? Я искренне не понимаю как можно писать код в таких условиях.


            1. DarthVictor
              08.09.2023 15:17

              При работе с чужими данными, а файл на диске - это чужие данные, описанная вами проблема точно также возникнет и в C++ и в Java. Внешние данные всегда требуется проверять и на типы и на валидность. Особенно тут отличился один андроидовский парсер, который со стандартными настройками кидал исключение при появлении нового поля в JSON. А андроидовское приложение - это не фронт на в браузере, его просто так не обновишь.


            1. Hardcoin
              08.09.2023 15:17
              +1

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


              1. Spaceoddity
                08.09.2023 15:17
                -1

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


                1. andreymal
                  08.09.2023 15:17
                  +2

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

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


                  1. Spaceoddity
                    08.09.2023 15:17

                    Чуть ниже ответил. Добавлю ещё от себя - обязательно сообщит. В 100500 раз, что очередная сущность не типизирована или об "уязвимости в виде :any"))

                    Вот где мазохизм!))


                1. Hardcoin
                  08.09.2023 15:17
                  +1

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

                  Человек, конечно, мудрее компилятора. Вот только брать на себя его работу вы будете, пока не лень. Через какое-то время наиграетесь. А компилятор не устает никогда, в этом преимущество.


                  1. Spaceoddity
                    08.09.2023 15:17

                    Но это в любом случае полумеры. Не понимаю я такого шаблонного программирования. "уяк-уяк и в продакшен", а если что не так, компилятор сообщит. Или не сообщит...


            1. Alexandroppolus
              08.09.2023 15:17

              Я вот не очень представляю как вместо номера может "нечаянно" прийти строка... Если я ожидаю номер - я и получу номер. Так что перманентный бардак с типами обычно как раз у адептов TS

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

              И всё это надо поддерживать, интерфейсы иногда меняются со временем. Т.е. нельзя в какой-то момент "развести бардак с типами", а потом жить-поживать. Процесс непрерывный.


              1. Spaceoddity
                08.09.2023 15:17
                -3

                Да хватит уже расписывать - понял я, понял. Там у вас какие-то совершенно непостижимые вещи происходят. Только ваша задача как раз с этими данными некие манипуляции производить, но если уж вы даже понятия не имеет что это за данные...


            1. SadOcean
              08.09.2023 15:17
              -1

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


              1. Spaceoddity
                08.09.2023 15:17
                -2

                То есть понятно, есть проблемы с входными данными, но после этого ты получаешь поведение, которому можно доверять.

                В том-то и дело, что нет. Пришла строка вместо числа - компилятор плюнул ошибкой в консоль. Всё. Проект все равно не функционален. А уж если у вас вместо одного числа пришло другое (а согласитесь, при таком бардаке в проекте - удивляться этому не приходится) - никакой TS не поможет.


                1. andreymal
                  08.09.2023 15:17
                  +4

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

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

                  Когда толпа пользователей прибегает жаловаться, что две книги по 9 в сумме стоят 99 — это катастрофа: техподдержка перегружена, чудовищный репутационный ущерб, и нужно срочно как-то найти, в каком конкретно месте число превратилось в строку (совсем не факт, что виноват именно бэк), и исправить желательно вчера


                  1. Spaceoddity
                    08.09.2023 15:17
                    -2

                    Это, видимо, какое-то новая парадигма программирования. Или я слишком стар стал уже для всего этого...

                    Вы рассказываете про "ОЧЕНЬ крупные проекты" и одновременно с этим у вас в продакшен вываливается подобное... Где тестовое окружение? Чем занят QA-отдел?

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

                    Вот этого я искренне не понмиаю Это как бы бэкенд должен делать и фиксить! Ну найдёте вы по быстрому что именно прилетает "не то". Дальше-то что?

                    Я не пойму прикола - это бэкендеры что ли TS так пиарят?))


                    1. andreymal
                      08.09.2023 15:17

                      Это как бы бэкенд должен делать и фиксить!

                      Почему? Это может быть осознанное и задокументированное изменение в API, и задача фронтенда — научиться работать с этим изменением.

                      Собственно, наивность и рейтинг ваших комментариев ещё раз демонстрируют, что с реальными проектами вы не особо работали)


                1. TheRikipm
                  08.09.2023 15:17
                  +1

                  "Зачем вы автотесты? Просто пишите без багов." (c)


    1. Shatun
      08.09.2023 15:17
      +8

      Поднимаем JSON с диска, парсим его в тип бала, в котором у нас есть поле бла, а на диске у нас лежала стринга. Что мы получаем? Мы получаем полу-статическую типизацию.

      Если у вас интеджер ожидается в json то везде в коде вы его ожидаете. По опыту в js нердеко он становится потом стрингой и никото незамечает. По-моему процентов 30 багов связано с этим(исклячая ошибки бизнеса)
      Если мне надо поменять тип поля или удалить его компилятор(ИДЕ) сразу покажет все места его использования.
      Если мне через год надо понять что в коде происходит то мне ненадо перерывать все доки чтобы узнать а чот же там моежт быть и какие еще поля есть в это json.

      В итоге, мне кажется, что я трачу больше времени на обслуживание компилятора Typescript и Eslint, чем на разработку ПО.

      Просто пишу код, компилятор выкидывает ошибки только если я где-то ошибся. Непонмню отдельных приседаний для компилятора.


      1. Spaceoddity
        08.09.2023 15:17
        +1

        Просто пишу код, компилятор выкидывает ошибки только если я где-то ошибся. Непонмню отдельных приседаний для компилятора.

        Потому что эти "приседания" (и ещё кучу всего в придачу) уже отработал линтер. Только попробуйте таб вместо пробелов влепить или кавычки не того сорта))


    1. Gruzchick
      08.09.2023 15:17

      Просто не асилил да и всё


    1. meded90
      08.09.2023 15:17

      в новом веб шторме поравили проблему с ошибками теперь они выводятся кросивым и понятным деревом. для вс кода тоже плагин есть


  1. Nipheris
    08.09.2023 15:17
    +17

    Что же, прощай, TypeScript. Пусть ты принесешь много строгости и удовлетворения своему племени, позволяя остальным наслаждаться JavaScript в том славном духе, в котором он был изначально задуман: Свободным от сильной (строгой) типизации.

    Не знаю, в каком там духе был задуман JavaScript, по-моему его вообще не задумывали писать больше 100 строк кода в одном приложении. Это теперь его толковые люди пытаются дотянуть до приличного уровня, как улучшением самого ECMAScript, так и новыми языками. Я не могу относится серьёзно к языку, в котором до сих пор нет нормальной возможности создать композитный тип с equality-by-value, т.е. запись.

    Ну а вообще, я думаю всё зависит от ожиданий от языка и вообще от написания кода. Вот допустим для чего лично я пишу код? Что я ожидаю от результата? Я ожидаю, что путём вложения большого количества времени и путём итеративных улучшений смогу создать систему из большого количества элементов, большинство из которых у меня в голове не могут поместиться за один раз. Но благодаря типам, модулям, проверкам во время компиляции и т.д. я могу с помощью ВРЕМЕНИ и УПОРСТВА (труда) повысить КАЧЕСТВО моего результата. Поэтому я работаю в проектах, где нужно достаточно высокое качество. Я люблю надёжные системы, мне неинтересно писать быстро и на "сойдёт", я уже старый для этого, пора создавать надёжный и полезный код, пара мгновений - и ты уже пенсионер, и слишком медленно тормозишь.

    Другие же люди создают стартапы за пару недель, им завтра нужен PoC, а послезавтра - работающая страница оплаты, чтобы брать денежку. И я не могу их в этом винить, они строят бизнес, возможно они завтра будут менять мир вокруг меня. Нужны ли им пляски с типами и с ошибками компиляции? Наверное нет.


    1. nin-jin
      08.09.2023 15:17
      +6

      Всмысле нет? За час набросал код. ТС ткнул меня носом, где я ошибся. Быстро пофиксил и зарелизил. Без ТС я бы ещё сутки дебажил в поисках глупой опечатки.


      1. formerchild
        08.09.2023 15:17

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


  1. impwx
    08.09.2023 15:17
    +5

    Статья в одном предложении: "Любителю Ruby не понравился Typescript". С учетом философии этих языков, я был бы удивлен услышать обратное.


    По поводу жалоб на "полу-статическую типизацию" — обычно так выходит, если человек приходит со знанием языка X и ждет, что в TS поведение некой фичи будет точно таким же, а оно оказывается иным. Конечно, программист на фортране может на любом языке писать на фортране, но будет ожидаемо больно. Не надо так!


    В TS действительно многие вещи работают непривычно. Дело в том, что у него изначально была уникальная задача: попытаться обуздать семантику абсолютно безумного языка, коим является JS. И решили ее, конечно, не без отдельных косяков, но в целом очень неплохо.


    Конкретно для проблемы из комментов выше: если вы работаете со сторонним бэкендом, который вы не контролируете, или с произвольными файлами с диска, которые кто-то мог попячить, то есть чудесная библиотека для контроля типов в рантайме:


    https://github.com/gcanti/io-ts


    1. novusnota Автор
      08.09.2023 15:17
      +1

      Ух ты, спасибо, любопытно. Пока на поверку выглядит, как Zod :)


      1. lam0x86
        08.09.2023 15:17

        Почитал первый комментарий, сразу захотел написать про zod, про который, комментатор, видимо, не слышал.


    1. Spaceoddity
      08.09.2023 15:17

      абсолютно безумного языка, коим является JS

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


      1. DirectoriX
        08.09.2023 15:17
        +3

        Например, сортировку массива чисел по значению, а не лексикографчески :)


        1. Spaceoddity
          08.09.2023 15:17

          Гы-гы, а ещё он числа складывать не умеет - 2 + '2' = '22'


          1. nin-jin
            08.09.2023 15:17


      1. slonopotamus
        08.09.2023 15:17

        Под какие задачи задумывался JS?


      1. impwx
        08.09.2023 15:17
        +1

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


        1. Spaceoddity
          08.09.2023 15:17

          Но теперь задачи другие

          Может проблему стоит поискать тут? А то повадились бизнес-логику на клиенте считать))


    1. ValentinAndreev
      08.09.2023 15:17

      В Ruby тоже есть типы, не так, конечно как в TS.


  1. ImagineTables
    08.09.2023 15:17
    +1

    Приятно сознавать, что ты не сошёл с ума и кто-то ещё (какой-то создатель какого-то Ruby on Rails) думает так же.


    Единственное, что — в отличие от автора я не считаю ES очень хорошим языком. Строгости при работе с типами ему действительно не хватает. Но это должно решаться не необходимостью описывать типы, а более строгими правилами при работе со значениями. Дайте мне superstrict, при котором бы на попытку 2 + '3' (или любое другое несоответствие) вылетало исключение — и вот тогда я буду счастлив.


    1. novusnota Автор
      08.09.2023 15:17
      +1

      Добро пожаловать в Python или Ruby :)


      1. iliazeus
        08.09.2023 15:17
        +1

        в Python

        Вот я что-то не уверен, что в нем с этим строже.

        2 * "2" == 4
        2 * "2" == "22"
        

        Угадаете, где какой язык? :)


        1. novusnota Автор
          08.09.2023 15:17

          Хм, ну тут же не приведение типов, а заложенная работа оператора * для удобного построения строки из N подстрок


          1. iliazeus
            08.09.2023 15:17

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


      1. ImagineTables
        08.09.2023 15:17

        Добро пожаловать в Python или Ruby :)

        К счастью, браузер, для которого я чаще всего пишу, уже поддерживает такой строгий скриптинг (и это не Python или Ruby).


        Добавлю, что эта (и некоторые другие) особенность настолько важна для меня, что я даже готов пожертвовать кросс-браузерностью (такой код не получится запустить в CEF).


        Общий тренд изменений в ES достаточно оптимистичен. Например, на первом месте в документации по strict mode стоит:


        1. Eliminates some JavaScript silent errors by changing them to throw errors.

        Даст бог, в новых версиях ES и BaNaNa'вые фокусы пофиксят, потому, что в реальных проектах от них гораздо больше вреда, чем пользы.


    1. Uint32
      08.09.2023 15:17
      +1

      Поддерживаю. Динамическая типизация должна быть строгой!


    1. iliazeus
      08.09.2023 15:17
      +4

      Дайте мне superstrict, при котором бы на попытку 2 + '3' (или любое другое несоответствие) вылетало исключение

      И потом пытаться по стектрейсу какой-нибудь sum() понять, откуда именно в нее пришла строка вместо числа? Вместо того, чтобы IDE сразу, ещё до запуска кода подсветила место, где я при рефакторинге забыл поменять тип поля.


      1. ImagineTables
        08.09.2023 15:17
        +1

        Я бы понял, если бы речь шла про Java. Про их километровые колстеки рассказывают анекдоты. Но ES? Размотать любое исключение там совершенно не проблема. Проблема в том, когда оно не происходит, а даёт неожиданный результат.


        Что касается подсветки. Во-первых, предлагаю перечитать статью. Там объясняется, что это удобство совсем не бесплатно. Компиляция в человеческом пайплайне — это всегда высокая цена. Во-вторых, в реальности такие ошибки происходят отнюдь не по простым сценариям, которые можно было бы подсветить (как и в C/C++ — там есть компиляция, и ошибки, к сожалению, тоже есть). В-третьих, существуют тесты, их и надо использовать — а компиляция слишком слабый вид тестирования, который другие виды заменяют на все сто.


        1. Kenya-West
          08.09.2023 15:17

          Но ES? Размотать любое исключение там совершенно не проблема.

          Нет. То есть, да - вы, может быть, даже в половине случаев правы, а в случае пет-проектов - в подавляющем большинстве.

          Но попробуйте размотать стектрейсы в Nest, который работает поверх Fastify, который работает поверх Deno, который работает поверх V8, когда выбивает абстрактную ошибку типа Unexpected end of form at Multipart._final in Multer в методе контроллера, который обклеен десятью декораторами (и ещё пятью декораторами-инжектами в конструкторе) и двумя интерцепторами. Абсурдность сей ошибки ещё и в том, что Multer юзается исключительно в Express, хотя у меня вместо Express под капотом Nest'а стоит Fastify.

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

          А виноват, кажется, был неправильно примененный декоратор в конструкторе класса контроллера, который почему-то в PUT-запросах с типом тела multipart/form-data импортировал этот Multer и пытался работать с моим проектом, как будто он запущен на Express. Кинул мейнтейнеру ишью, посмотрим, как будет...


          1. ImagineTables
            08.09.2023 15:17

            Программист на Джаве на любом языке будет писать на Джаве )))


            Я немного подумал, и мне теперь кажется, что тут проблема несколько сложнее, чем «динамическая типизация vs. статическая». Тут, скорее, конфликт методологий. И если брать тяжеловесную, где фреймворк фреймворком погоняет, очень может быть (я не знаю, опыта такого нет), что компиляция TypeScript'а действительно чем-то облегчает жизнь по сравнению с анализом исключения. А вот какой вывод из этого делать… Я такие системы не люблю, потому что считаю, что сложность в них недостаточно изолирована. Ну куда это годно, в самом деле: колстек на 100+ позиций? Для сравнения, в Windows-приложении он будет, максимум, в два десятка глубиной, а потом — ntdll.dll или kernel32.dll. Это ведь не говорит о том, что все Windows-приложения поголовно проще энтырпрайза, это говорит, что там изоляция лучше спроектирована.


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


        1. AnthonyMikh
          08.09.2023 15:17

          Размотать любое исключение там совершенно не проблема.

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


          1. ImagineTables
            08.09.2023 15:17

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


  1. LyuMih
    08.09.2023 15:17
    +3

    А потом через пару лет статья: "Turbo 12 переписали на TypeScript"


    1. czz
      08.09.2023 15:17
      +1

      На Golang + WASM


  1. Dartess
    08.09.2023 15:17
    +1

    JavaScript — это язык необходимости (если не учитывать WebAssembly, прим. перевод.)

    JavaScript остается необходимостью и с WebAssembly, хотя бы для того чтобы запустить его или манипулировать DOM


  1. vit1251
    08.09.2023 15:17

    А можно пример использования фреймворка Turbo и какой-то учебник или хотя бы пример уровня TODO приложения, а то событие конечно инетресное, но может проект уровня домашнего баловства у какого-то там подгоревшего Ruby-ста. Да и Basecamp тоже не фонтан как-бы даже в свое время... Так что хотелось бы тестимониалсов для вразумительно убедительного доказательсвта, что автор не просто олень, а уважаемы дон и его мнению надо верить...


  1. hVostt
    08.09.2023 15:17
    +8

    Вообще-то данные типизированы. Если ожидаешь число, должно приходить число. Что можно сделать с ценой товара, которая пришла в виде "бла-бла-ой-не-то"? Вывалиться в ошибку? Обмазать динамическими проверками? Какой смысл в динамике в самом принципе? Какой смысл в JSON рандомного формата? Системы обмениваются конкретными моделями с конкретными типами, а не по принципу "как фишка ляжет". Если же автор борется с типами, значит он делает что-то не так изначально. И ему ничего не поможет. Не ES6+, ни TS, ничего.


  1. Lexicon
    08.09.2023 15:17
    +1

    Такое обсуждение, будто это, - серьёзная тема, а не детская хотела автора.

    Не холиввр "JS vs полноценные языки", а "я хочу сделать JS в проекте хуже". Typescript, в сути, - инструментарий вокруг JS, ставший подобием стандарта.

    У разработчиков на руках все карты, хочешь, - используй типы, чистый JS в TS файлах, хочешь, - решай для каждой отдельной папки. Есть объективные причины не использовать TS, но искоренять его поддержку причин нет.


    1. EireenK
      08.09.2023 15:17
      +2

      Прямо религиозное бинго:


      • Это детская хотелка, а не мнение!
      • JS без тупоскрипта неполноценный язык!
      • Это стандарт! Все 95% мух так делают!
      • Искоренять его причин нет, атвечаю.

      Есть объективные причины не использовать TS

      Ну да, ну да. Попробуй заяви о них, прибегают такие как вы и закидывают ка "сильными аргументами", обозначенными выше.


      1. Lexicon
        08.09.2023 15:17
        +1

        Ну так это, вперёд

        А то слов мне в рот положить успели, а единственное утверждение не тронули

        Edit: аж неправильно прочел, неужели вы буквально обвинили меня в том, что "такие как я" не поддержали бы.. Моё высказывание?


        1. EireenK
          08.09.2023 15:17
          +1

          Большой проект без TS, десяток разработчиков. Не могу вспомнить, когда у меня в последний раз всплывала ошибка вида "подставлен String вместо Number, объект вместо скаляра". А если всплывает, то мгновенно видна при отладке или на крайний в юнит-тестах. И вот заставляют городить лишнюю тонну кода ради этих примитивных ошибок. Я какой-то особенный сверхвнимательный уникум, как и гонщик из статьи? (хах, я как раз гоночные игры люблю). Или это люди, которые боготворят TS, очень неуверенно чувствуют себя в JavaScript или имеют проблемы с концентрацией? Джуны; посредственные мидлы; люди, пересевшие с типизированных языков; просто ненавидящие JS, но пересевшие на него, т.к. "тут золота больше".


          Один плюс TS для меня неоспорим — code completion. Но за год работы над текущим проектом уже въелись в подкорку сигнатуры часто используемых функций. Как и "родные" JS-функции за годы работы с ним. Если надо использовать более редкую функцию, в любом случае иду отдельно в документацию перечитывать.


          1. nin-jin
            08.09.2023 15:17
            +2

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


          1. Lexicon
            08.09.2023 15:17

            Вы по итогу свой личный опыт будете приводить как аргумент? Сухо и наивно


            Во-первых, в моем комментарии ясно прослеживается тезис, - TS, - инструментарий, его использование гибко настраивается на уровне репы/папки/файла, мой аргумент соответственно, - нет причин бороться с инструментом, это как запретить открывать код в Idea, notepad only please.

            На мой взгляд, основное преимущество использования TS, - самодокументируемый код и интегрированность разработки. То есть, более удобный способ наследования типов/аргументов, чем был бы в JSDoc.

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

            Соответственно, во-вторых, вы забыли, что не все сидят на одном проекте годами, в особенности, когда вы начнете называть себя тех-лидом, а к "джунам и посредственным мидлам" прибавите "ленивых синьоров". Возможно вы поймете, что в большом проекте может быть и 100 человек, на уровень которых вы не сможете повлиять, а проектов, начатых не вами, может стать с десяток.


            В-третьих, с чего вы взяли, что всем нравятся юниты? Особенно их читать? И особенно их писать "чтобы не городить код"? Запускать код и тесты, чтобы проверить, работает ли он, я может и так знаю, что работает.

            Гонору много, имхо, аргументируете как джун


  1. yrub
    08.09.2023 15:17
    -2

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


  1. Format-X22
    08.09.2023 15:17

    Как говорится - а теперь отрефакторите мне этот трёхлетний проект, который писало 6 человек, на чистом JS.

    TS это когда ты делаешь что-то сложное и на долго, особенно если это NodeJS и падение будет аффектить сильнее кривого рендера. А ещё инструментарии IDE, которые с TS позволяют переименовывать, перемещать, менять структуру и как угодно танцевать с кодом и всё с гарантией обновится где нужно. А с JS гарантий нет и добро пожаловать в дебаггер.

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


    1. aavezel
      08.09.2023 15:17

      Легко если есть тестовое покрытие на типы )