company_banner

Чем хорош (и чем плох) Typescript: опыт UI-разработчиков

    Здравствуйте, меня зовут Александр Черников. Я руковожу разработкой UI проекта “Цифровой корпоративный банк” — обновлённой версии Сбербанк Бизнес Онлайн, интернет-банка для юридических лиц. Мы разрабатываем stand-alone клиент, мобильное приложение и, собственно, web-клиент, о котором и пойдёт речь. В своих статьях я буду делиться ценным опытом нашей команды, а конкретно в этом посте опишу наш технологический стек и остановлюсь на том, почему мы выбрали Typescript в качестве основного языка.




    Новую версию Сбербанк Бизнес Онлайн мы пишем 2,5 года. Уже в следующем году мы планируем перевести на него всех корпоративных клиентов Сбербанка.

    Итак, начнем со стека. Мы внедрили TypeScript, React, Reflux(legacy), Redux, Bluebird Promise и Bootstrap. Стили пишем на LESS. Все это добро мы собираем с помощью Babel, Webpack и его плагинов. Webpack пока первой версии, но собираемся перейти на вторую. Многие могут спросить: зачем нам Typescript и Babel одновременно? Во-первых, раньше TypeScript не все умел транспилировать, и только недавно сравнялся с Babel по этой функциональности. Во-вторых, TypeScript не умеет кэшировать. А babel умеет хранить готовые ES5 скрипты в папке. Если исходники не поменялись, он сразу берет их оттуда. Когда проект собирается несколько минут, такая экономия времени очень радует.

    Стек технологий достаточно свежий. Ребятам приходится вникать сразу в несколько вещей: например, в TS, React, Redux, в сам проект и в термины нашего банка. Из 50-60 человек только 20 процентов работают в штате, остальные подключаются от вендоров и часто меняются.

    Как мы справляемся в таких условиях с code-review? Раньше несколько самых опытных разработчиков смотрели код всех команд, была такая небольшая пирамида. Сейчас мы стараемся равномерно распределить по командам. Во многих командах появились так называемые эксперты (хорошо разбираются в проекте, знают, что и где лежит), чтобы не изобретали велосипеды и прочее. Соответственно они review’ят не только ребят из своей команды, но и из других.

    Review у нас немного автоматизировано и на pull-request у нас добавляются лейблы, которым нужно соответствовать. Тогда они станут зелеными и ПР автоматически сольется. Лейблы есть разные: Code-style, Expert, Architect, CSS, E2E-test и другие. Если меняются .less файлы — добавляется CSS, если меняется какой-то код ядра или низкоуровневых вещей — добавляется Architect. Чтобы получить Expert, нужно набрать как минимум 2 аппрува экспертов.
    И если человек новенький на проекте или не очень силен в JS, тогда его код будет сильно отличаться от того, что было до code-review.

    TypeScript и JavaScript


    Я застал тот момент, когда многие писали на TS и использовали новые фичи, которые транспилируются в ES5. Но даже тогда мы использовали TS для типизации, для некоего статического анализа кода на ошибки. Да, на JS можно написать код грамотно и правильно, но он тебя не подстрахует так, как TS. Кто-то ставит в минусы, что приходится много писать TS-кода (overhead), т.е. типизация, типы, интерфейсы и др. Когда мы рефакторили “старый” код JS > TS, то выявлялись элементарные ошибки, которые сработают только в runtime. То запятая не там стоит, то точку забыли, то скобки рано закрыли и т.д., не говоря уже про недосягаемый код и неиспользуемые аргументы и пр… Когда система большая и команда не может покрыть всю систему тестами, то TS спасает. При 3000-4000 скриптах вообще трудно представить, как жить без TS.

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

    Мы часто спорим по этому поводу. Некоторые коллеги говорят: “А зачем нам TS? Мы пишем код грамотно и проводим тщательно code-review, отбираем людей на собеседовании, да и вообще джедаи JS”. Но ведь человеческие факторы никто не отменял: лень, торопливость, невнимательность. Ничего не мешает подключить TS к вашему JS-коду. Если у вас действительно нет ни одной ошибки, то компилятор ничего не найдет — можете радоваться тому, что у вас отличная команда, и звезды сложились как надо. Но перестраховаться с помощью TS все равно не мешает. Тем более, что и особых затрат это не потребует.

    К тому же, в этом году в версии 1.8 в TS сделали удобную фичу. Теперь можно проверить типы в чистом JS — достаточно добавить файлы “.js” в проект и allowJs флаг. Если есть какой-то код, который не хотите проверять, то спокойно его можно игнорировать через аннотацию @ts-nocheck. Во время code-review мелкие баги отловить почти нереально, а TS помогает экономить силы и время. А не то подольешь релизную ветку в develop с конфликтами в 100 файлах… хотел бы я посмотреть, как человек хладнокровно нажмет кнопку MERGE.

    TypeScript vs Flow


    “А как насчет Flow?” — спросите вы. Мы выбирали между ES6 и Typescript, про Flow тогда никто не знал. Для тех кому интересно, в чем разница их статического анализа кода, могу посоветовать интересный доклад Ильи Климова с конференции HolyJS 2017 Piter, где он сравнивает TypeScript и Flow.

    Ложки дегтя


    Помимо overhead у Typescript есть еще несколько недостатков:

    1. Существенное замедление сборки проекта. Но это, опять же, исключительно в нашей специфике сборки: Webpack + TS + Babel. У кого такая же конфигурация (+- babel), могу посоветовать использовать загрузчик ts-loader обязательно с флагом transpileOnly, а TSC запускать параллельно. А в режиме инкрементальной сборки (--watch), держать 2 процесса отдельно: webpack --watch и tsc --watch.
    2. Возникают проблемы с OutOfMemory ошибками nodeJS, особенно неприятны такие сюрпризы, когда нужно собрать проект и выпустить релиз через 3-4 дня, а быстро решить их не получается.
    3. Необходимость актуализации версий .d.ts для внешних библиотек. Слава Богу, закончилась пора с tsd > typings. И теперь все можно качать сразу через npm > @types. А что если вышла новая версия библиотеки, lodash например, а .d.ts еще нет? Тогда приходится выбирать: дописать самому (в репозиторий или выложить ПР на github в репозиторий DefinitelyTyped) или пока не использовать эту фичу.
    4. Поиск разработчиков с опытом на TypeScript. Это отдельные слезы нашего HR. Насколько мне известно, на рынке у всех сейчас проблема с поиском “продвинутых” frontend-разработчиков с опытом написания серьезных SPA, Angular | React | Vue, Typescript, Redux и пр.
    Сбербанк 101,19
    Компания
    Поделиться публикацией
    Комментарии 69
    • +11

      В целом поддерживаю, только Babel на мой взгляд уже давно не нужен.


      Webpack пока первой версии, но собираемся перейти на вторую.

      Уже версия 3 давно.


      TypeScript не умеет кэшировать. А babel умеет хранить готовые ES5 скрипты в папке.

      Awesome-typescript-loader. Он умеет кешировать и компилить асинхронно

      • –2
        В целом поддерживаю, только Babel на мой взгляд уже давно не нужен
        А как же гибкость? У бабела хорошая база transformation плагинов и их апи пока лучше, чем в ts.

        В 7м бабеле (пока еще бета) запилили поддержку синтаксиса typescript: babel-preset-typescript. Так что можно сказать, что и ts для целей сборки не нужен.

        Интересно, что будет, если в flow запилят поддержку ts и плагинов для Language Service API?
        • 0
          у нас как раз с ним (awesome-typescript-loader) вышла трабла: куча ошибок Duplicate identifier '...'. и пришлось вернутся на ts-loader

          возможно ошибка актуальна только для нашего набора пакетов
          • 0
            у нас как раз с ним (awesome-typescript-loader) вышла трабла: куча ошибок Duplicate identifier '...'. и пришлось вернутся на ts-loader

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

            Нет, github.com/s-panferov/awesome-typescript-loader/issues/135
          • 0

            Да, мы в курсе про вторую :) думаю, там с переходом небольшая разница.
            Пробовали atl — не увидели роста производительнсти. В любом случае проверку типов мы в тот же процесс сборки не вернем — это все равно затратно.

            • 0

              TS -> EsNext -> Babel — лучший вариант — поддержка плагинов + конфигурируемая транспиляция

            • 0
              Очень сложно вас воспринимать всерьез, когда прод иногда показывает большие белые страницы без контента, а прямо сейчас например в логе (не банка, сайта), куча вот такого:
              Заголовок спойлера
              Public-Key-Pins: Сайт указал заголовок, который не удалось успешно распарсить.[Подробнее] ManageableArea.css
              Public-Key-Pins: Сайт указал заголовок, в который не был включён подходящий pin.[Подробнее] template.js
              Public-Key-Pins: Сайт указал заголовок, в который не был включён подходящий pin.[Подробнее] template.js
              Public-Key-Pins: Сайт указал заголовок, который не удалось успешно распарсить.[Подробнее] ManageableArea.js
              Public-Key-Pins: Сайт указал заголовок, в который не был включён подходящий pin.[Подробнее] template.js
              Public-Key-Pins: Сайт указал заголовок, в который не был включён подходящий pin.[Подробнее] template.js
              Public-Key-Pins: Сайт указал заголовок, в который не был включён подходящий pin.[Подробнее] template.js
              Public-Key-Pins: Сайт указал заголовок, в который не был включён подходящий pin.[Подробнее] template.js
              Public-Key-Pins: Сайт указал заголовок, который не удалось успешно распарсить.[Подробнее] targetingContainer.js
              Public-Key-Pins: Сайт указал заголовок, который не удалось успешно распарсить.[Подробнее] aurora.containers.js
              unreachable code after return statement[Подробнее] portallibs-core.min.js:54:81196
              unreachable code after return statement[Подробнее] portallibs-core.min.js:54:112675
              unreachable code after return statement[Подробнее] portallibs-core.min.js:54:113265
              unreachable code after return statement[Подробнее] portallibs-core.min.js:54:129537
              unreachable code after return statement[Подробнее] portallibs-core.min.js:54:132732
              unreachable code after return statement[Подробнее] portallibs-core.min.js:54:134699
              unreachable code after return statement[Подробнее] portallibs-core.min.js:54:147881
              unreachable code after return statement[Подробнее] portallibs-core.min.js:54:147971
              unreachable code after return statement[Подробнее] portallibs-core.min.js:54:149320
              unreachable code after return statement[Подробнее] portallibs-core.min.js:54:229550
              unreachable code after return statement[Подробнее] portallibs-core.min.js:54:253789
              unreachable code after return statement[Подробнее] portallibs-core.min.js:54:264000
              unreachable code after return statement[Подробнее] portallibs-core.min.js:54:266888
              unreachable code after return statement[Подробнее] portallibs-core.min.js:73:2434
              window.controllers/Controllers является устаревшим. Не используйте его для определения UA. portallibs-core.min.js:54:25181
              Синхронный XMLHttpRequest в основном потоке является устаревшим из-за его пагубного влияния на работу конечного пользователя. Для получения дополнительной помощи обратитесь к xhr.spec.whatwg.org portallibs-core.min.js:2:81642
              Public-Key-Pins: Сайт указал заголовок, который не удалось успешно распарсить.[Подробнее] loader_bundle.min.js
              Public-Key-Pins: Сайт указал заголовок, который не удалось успешно распарсить.[Подробнее] header.js
              Public-Key-Pins: Сайт указал заголовок, который не удалось успешно распарсить.[Подробнее] sbt.js
              Public-Key-Pins: Сайт указал заголовок, который не удалось успешно распарсить.[Подробнее] atc-libs.min.js
              Public-Key-Pins: Сайт указал заголовок, который не удалось успешно распарсить.[Подробнее] Breadcrumb.js
              Public-Key-Pins: Сайт указал заголовок, который не удалось успешно распарсить.[Подробнее] push-notifications.js
              Public-Key-Pins: Сайт указал заголовок, который не удалось успешно распарсить.[Подробнее] common.maven.min.js
              Public-Key-Pins: Сайт указал заголовок, который не удалось успешно распарсить.[Подробнее] SBO.svg
              Public-Key-Pins: Сайт указал заголовок, в который не был включён подходящий pin.[Подробнее] content
              Public-Key-Pins: Сайт указал заголовок, в который не был включён подходящий pin.[Подробнее] identifier
              Public-Key-Pins: Сайт указал заголовок, который не удалось успешно распарсить.[Подробнее] shared.css
              Загрузка
              • –1

                Вы показываете что-то странное, уверены что это с сбербанк бизнес онлайн? Поверьте мне, если у нас на каких-то страницах просто белый экран — мы уже про это знаем и скорее всего это уже починено ;)

                • 0

                  Возможно один из ваших плагинов в браузере что-то ругается.

                  • –3
                    VM346:2 Refused to connect to 'https://127.0.0.1/' because it violates the following Content Security Policy directive: «connect-src 'self' bf.sberbank.ru:9443 *.group-ib.ru sbrf.livetex.ru www.google-analytics.com nlb-efsd1.sbrf.ru:444».

                    f.pb @ VM346:2
                    (anonymous) @ VM346:2
                    check @ VM346:2
                    (anonymous) @ VM346:2
                    setTimeout (async)
                    start @ VM346:2
                    f.K @ VM346:2
                    start @ VM346:2
                    d.tf @ VM346:2
                    (anonymous) @ VM346:2
                    (anonymous) @ VM346:2
                    (anonymous) @ VM346:2
                    setInterval (async)
                    a @ VM346:2
                    f.Vd @ VM346:2
                    (anonymous) @ VM346:2
                    (anonymous) @ VM346:2
                    (anonymous) @ VM345:1
                    (anonymous) @ VM345:1
                    x.onreadystatechange @ grlb.js?ver=27hf.001.00:18
                    XMLHttpRequest.send (async)
                    cb @ grlb.js?ver=27hf.001.00:18
                    VM346:2 Refused to connect to 'https://127.0.0.1:80/' because it violates the following Content Security Policy directive: «connect-src 'self' bf.sberbank.ru:9443 *.group-ib.ru sbrf.livetex.ru www.google-analytics.com nlb-efsd1.sbrf.ru:444».

                    f.pb @ VM346:2
                    (anonymous) @ VM346:2
                    check @ VM346:2
                    (anonymous) @ VM346:2
                    setTimeout (async)
                    start @ VM346:2
                    f.K @ VM346:2
                    start @ VM346:2
                    d.tf @ VM346:2
                    (anonymous) @ VM346:2
                    (anonymous) @ VM346:2
                    (anonymous) @ VM346:2
                    setInterval (async)
                    a @ VM346:2
                    f.Vd @ VM346:2
                    (anonymous) @ VM346:2
                    (anonymous) @ VM346:2
                    (anonymous) @ VM345:1
                    (anonymous) @ VM345:1
                    x.onreadystatechange @ grlb.js?ver=27hf.001.00:18
                    XMLHttpRequest.send (async)
                    cb @ grlb.js?ver=27hf.001.00:18
                    VM346:2 Refused to connect to 'https://127.0.0.1:22/' because it violates the following Content Security Policy directive: «connect-src 'self' bf.sberbank.ru:9443 *.group-ib.ru sbrf.livetex.ru www.google-analytics.com nlb-efsd1.sbrf.ru:444».

                    f.pb @ VM346:2
                    (anonymous) @ VM346:2
                    check @ VM346:2
                    (anonymous) @ VM346:2
                    setTimeout (async)
                    start @ VM346:2
                    f.K @ VM346:2
                    start @ VM346:2
                    d.tf @ VM346:2
                    (anonymous) @ VM346:2
                    (anonymous) @ VM346:2
                    (anonymous) @ VM346:2
                    setInterval (async)
                    a @ VM346:2
                    f.Vd @ VM346:2
                    (anonymous) @ VM346:2
                    (anonymous) @ VM346:2
                    (anonymous) @ VM345:1
                    (anonymous) @ VM345:1
                    x.onreadystatechange @ grlb.js?ver=27hf.001.00:18
                    XMLHttpRequest.send (async)
                    cb @ grlb.js?ver=27hf.001.00:18
                    VM346:2 Refused to connect to 'https://127.0.0.1:445/' because it violates the following Content Security Policy directive: «connect-src 'self' bf.sberbank.ru:9443 *.group-ib.ru sbrf.livetex.ru www.google-analytics.com nlb-efsd1.sbrf.ru:444».

                    f.pb @ VM346:2
                    (anonymous) @ VM346:2
                    check @ VM346:2
                    (anonymous) @ VM346:2
                    setTimeout (async)
                    start @ VM346:2
                    f.K @ VM346:2
                    start @ VM346:2
                    d.tf @ VM346:2
                    (anonymous) @ VM346:2
                    (anonymous) @ VM346:2
                    (anonymous) @ VM346:2
                    setInterval (async)
                    a @ VM346:2
                    f.Vd @ VM346:2
                    (anonymous) @ VM346:2
                    (anonymous) @ VM346:2
                    (anonymous) @ VM345:1
                    (anonymous) @ VM345:1
                    x.onreadystatechange @ grlb.js?ver=27hf.001.00:18
                    XMLHttpRequest.send (async)
                    cb @ grlb.js?ver=27hf.001.00:18
                    VM346:2 Refused to connect to 'https://127.0.0.1:5985/' because it violates the following Content Security Policy directive: «connect-src 'self' bf.sberbank.ru:9443 *.group-ib.ru sbrf.livetex.ru www.google-analytics.com nlb-efsd1.sbrf.ru:444».
                  • +2
                    4. Поиск разработчиков с опытом на TypeScript. Это отдельные слезы нашего HR
                    Я вас правильно понимаю, что вы ищете именно TypeScript разработчиков, не JS (остальной набор технологий достаточно популярный). Конечно JS и TS различаются, кроме типов еще различия в классах и т.п. Но все же много общего. Да и TS в итоге транслируется в JS.
                    • +2

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

                      • –2
                        кто дальше песочницы с ним работал — не так много.

                        Это вы про 18 летних студентов за 50 000 рублей?

                        200 000 рублей и такой специалист у вас в кармане
                        • 0
                          А за 250 не только в кармане да?
                          • 0
                            оооо) за 250 000 на галере будет примерно такие слова от директора: «Что, 250? больше чем у меня? Да кто он такой, там же всего лишь кнопку подсвечивать нужно через CSS, это же верстка, я в 1990 года сам такое делал на таблицах!!»

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

                            labor-union.wikia.com/wiki/Main
                            labor-union.wikia.com/wiki/Lifehacks
                            (СОВЕТУЮ ВСЕМ ПОЧИТАТЬ)

                          • 0
                            Ну вы знаете, месяц собеседований по 3 в день и да, 1 у вас в кармане:) А когда вам надо вывести хотя бы 6-7 человек за месяц?
                            А про студентов, скорее так: 25 летние новоиспеченные jsники после курсов, пару песочниц и они уже хотят далеко не 50.
                            • –1
                              Дефицита нет, а есть избыток. Достаточно зайти на LinkedIn, поискать анкеты людей и убедиться, что на территории РФ существует избыток квалифицированных кадров с обширными и углубленными знаниями и уклоном в различные специализации. При этом российские бизнесмены и «красные директора» любят распространять тлетворный миф о наличии на российском рынке труда дефицита кадров, согласных работать у них на проектах, и при этом забывают добавлять: "… за еду". Суть всех этих сказок про дефицит специалистов сводится к следующему. Бизнесмен или «красный директор» имеет в штате 50 инженеров, которым он суммарно платит в год 25 миллионов рублей. Он хочет начать тратить в год 20 миллионов рублей вместо 25 миллионов, продолжая иметь в штате то же самое количество специалистов, способных совершать в год то же самое количество человеко-часов труда. Поэтому бизнесмен хочет, чтобы количество инженеров на рынке удвоилось или утроилось, чтобы можно было резко понизить з/п текущим инженерам в штате, а на место уходящих инженеров всегда иметь возможность найти новых по еще более дешевой цене. Нередко бизнесмены и сами занимаются организацией курсов при вузах или заставляют своих лучших технических специалистов учить студентов или интенсивно доучивать выпускников с целью помочь бизнесмену раз и навсегда обвалить рынок труда. Многие старшие инженеры хорошо разбираются в своих областях, но обладают экономической безграмотностью, не читали Карла Маркса и не понимают, что они готовят для своего начальника промышленную резервную армию труда.

                              На все речи бизнесменов, рассказывающих о нехватке специалистов на российском рынке труда, нужно отвечать так: «С чего вы взяли, что в РФ есть нехватка квалифицированных кадров? Кто мешает лично вам зайти на LinkedIn и сегодня же найти на едином глобальном рынке труда русскоговорящих квалифицированных специалистов для вашего бизнеса, переманив их с других проектов? Если вам не хватает денег, то это ваши проблемы. Бизнесмену никто ничего не обещал. Ему некто не обещал, что его бизнес будет рентабельным. Вы — лузер, и ваш бизнес не имеет права на существование, потому что вы не вписались в рынок»
                        • +4

                          У меня такая же реакция была. 2 дня, ну максимум неделя понадобится программисту чтоб освоиться с ТС. Это если он ну совсем никогда не сталкивался со строго-типизированными языками. Да, придется разобраться с дженериками и смириться с тем, что ты не можешь передавать и возвращать всё что угодно куда угодно (что в итоге пойдёт только на пользу). Причем писать и понимать код программист начнёт сразу, а не через 2 дня.

                          • 0

                            Ой не скажите.
                            Когда в аргумент передается функция все становится тяжело
                            const negate = (fn: Function) => (...args: any[]) => !fn(...args)
                            Или когда пробуешь описать React типы.
                            Дженерики говорите простые?
                            Вот я писал


                            export const mapReplace = <A extends {}, U extends {}>(
                              array: A[],
                              test: (item: A) => boolean,
                              replacement: (item: A) => U
                            ): (A | U)[] => {
                              return array.map((item: A) => {
                                return test(item) ? replacement(item) : item
                              })
                            }

                            И как вам такое? Сходу понятное?


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


                            <T>size(objectOf<T>) => number 

                            это не правильный генерик. Должно быть any вместо T

                            • 0

                              Что-то вы сами себе все усложнили.


                              export function mapReplace<A,U>(
                                array: A[],
                                test: (item: A) => boolean,
                                replacement: (item: A) => U
                              ): (A | U)[] {
                                  return array.map(item => test(item) ? replacement(item) : item);
                              }

                              Нормально пишется и читается.

                              • 0

                                Без


                                mapReplace = <A extends {}, U extends {}>

                                не заработает из-за конфликта с jsx (хотя я сейчас проверил — у меня заработало, магия какая-то)
                                https://stackoverflow.com/questions/32696475/typescript-tsx-and-generic-parameters


                                Ну а функцию да, можно в одну строку записать

                                • 0
                                  Два параметра уже не удовлетворяют синтаксису tsx, а потому их можно использовать без проблем.

                                  Кроме того, ключевое слово function также исключает понимание угловых скобок как тэга.
                                  • 0
                                    > не заработает из-за конфликта с jsx

                                    Так это проблема jsx. TS тут при чем?
                                    • 0

                                      jsx+TS = tsx в котором и не работает

                                • +1
                                  Когда в аргумент передается функция все становится тяжело

                                  Ну что вы хотите, писать на «фп» и чтобы у вас из ноги кровь не текла? Тут или одно или другое

                                  И как вам такое? Сходу понятное?

                                  Мне меньше всего понятен смысл этого: (A | U)[]. Зачем массив с двумя разными типами? Как с ними работать вообще? То есть вот у вас есть A[], с ним понятно как работать, а потом, после этой функции в этом массиве начинает попадаться то A, то U. А потом как? if (x instanceof U) ? Код, конечно, не самый изящный, но проблема скорее в архитектуре.

                                  Плюс еще названия. A и U — просто рандомные буквы? Вот так было бы значительно понятнее:
                                  export function mapReplace<TCurrent, TReplace>(
                                    array: TCurrent[],
                                    test: (item: TCurrent) => boolean,
                                    replacement: (item: TCurrent) => TReplace
                                  ): (TCurrent | TReplace)[] {
                                      return array.map(item => test(item) ? replacement(item) : item);
                                  }


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

                                  Проблемы с этим кодом две — неправильная архитектура и именование переменных. Как видите, TS в этом списке нету.
                            • –2
                              Все описанное в статье является устаревшим, как минимум на год и самое главное что не указаны сильные и слабые стороны, как было заявлено в заголовке. Хорош — система типов с продвинутым выводом типов, учит писать правильный код. Плох — когда разработчики начинают писать :type, они уже себя считают typescript разработчиками (особенно это касается js dev only) и мне кажется что 99% разработчиков не понимают с чем они работают на самом деле. TypeScript это не java и не c#. TypeScript, это типизация следующего поколения. Кроме того, не сложно описать типы для кода, сложно описать типы для библиотек. один раз было что пол дня не мог тип описать.
                              • +1
                                И ts сравнивать с flow не корректно, так как у них разные виды типизации. То есть, они различаются как яблоко и iphone.
                                • +1
                                  Объясните плиз на пальцах, в чем разница
                                  • +1

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


                                    Собственно, на первый взгляд flow и ts про одно и то же. Если немного приглядеться, то flow всё же больше про js + types и система типов более правильная. Зато у ts сильно лучше туллинг и сильно больше библиотек уже искоробки. Потому ts всех и победил. Хотя, как по мне, flow интереснее.

                                  • 0
                                    Разные виды типизации нужны для достижения одной цели: обнаружение ошибок до запуска проекта и они элементарно сравниваются по усилиям, необходимыми для внедрения и по количеству обнаруженных ошибок.
                                  • +2
                                    таковы суровые реалии бизнеса, самые новые технологии в проекте будет использовать либо идиот либо гений, так как технология зачастую ещё сырая, разработчиков умеющих пользовать её практически нет, из этого получаем снижение скорости и качества разработки.
                                    так что год это ещё очень даже неплохо

                                    а TypeScript, да, я считаю это прорыв, очень удобный и выразительный язык, особенно после js
                                    • 0
                                      TypeScript, это типизация следующего поколения

                                      А можно поподробнее? Очень любопытно.

                                    • 0

                                      Радует, что две из четырёх описанных болячки вылечили еще в прошлом году.
                                      Интересно, а есть ли статьи, описывающие негативный опыт внедрения TS? У меня лично от него позитивные впечатления, не понимаю почему многие его боятся.

                                      • 0

                                        Бесятся потому-что надо учить новый язык, а это "сложно и долго"

                                      • +2
                                        У нас в компании все перешли на TypeScript. Все довольны.
                                        • 0
                                          Ребятам приходится вникать сразу в несколько вещей: например, в TS, React, Redux, в сам проект и в термины нашего банка.

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

                                          Да, на JS можно написать код грамотно и правильно, но он тебя не подстрахует так, как TS.

                                          А в случае с Eclipse это невозможно вообще, только не говорите, что вам таки купили WebStorm??? )))

                                          Необходимость актуализации версий .d.ts для внешних библиотек. Слава Богу, закончилась пора с tsd > typings. И теперь все можно качать сразу через npm > @types.

                                          И не мешает отсутствие интернета? Nexus разве уже поддерживает @группы?
                                          • 0
                                            1) У новеньких есть на это время, мы же не заваливаем их сразу багами или доработками. И учетки и доступ даются быстрее, чем 3 месяца;) возможно вам не повезло с проектом и ответственными.
                                            2) У нас круче — Idea.
                                            3) У нас nexus поддерживает @subfolder и есть интернет. В двух словах: когда общий нексус СБТ не поддерживал, суперадмины нашего проекта подняли свой (новой версии) специально для нас, а позже мы вернулись в общий. Все решается, было бы желание!
                                            • 0
                                              1) HRы будут довольны таким ответом
                                              2) Про «круче» — холивар, но не в этом дело. Idea тоже денег стоит, значит на воровонной сидите или с личными лицензиями, что по внутренним порядкам запрещено.
                                              3) Привет Anykeyеву
                                          • 0
                                            а можно какие то кейсы где ts лучше js?
                                            не халивара ради, в мир js я пришел из java — привык к строго типизированным языкам, но учитывая весь сахар es6/es7 у меня еще не было ни разу ситуации в которой мне реально не хватало бы типизации в js
                                            В разрезе react мне за глаза хватает типов в PropTypes
                                            я не против ts но вопрос зачем остается открытым, хотелось бы какого то реального сравнения такой то кейс на js пишется за столько то на ts за столько, есть риск вот таких багов и экономия в будущем такая
                                            • +6

                                              Из очевидных:


                                              1. Code completion как у взрослых языков (новому программисту гораздо проще понять код)
                                              2. Видишь все ошибки при рефакторинге. Мы как-то переносили проект с angular 1 на angular 2, так у меня после переноса и изменения (допила-перепила) нескольких десятков файлов всё заводилось с первого раза. За годы работы со сквозной типизацией такое воспринимается как чудо
                                              3. Застрахован от очень многих ошибок рантайма. Тот же PropTypes покажет вам ошибку только когда она уже случилась (поправьте если это не так). Как говорится, со строгой типизацией сложнее по случайности отстрелить себе ногу. Например, при использовании Promise.all вы получаете массив значений в результат. И вот тут очень легко всё зафакапить, по ошибке указав не тот индекс. Тайпскрипт такого не допустит.
                                              • –4
                                                1, 2 во многом решает webstorm, 3 не совсем корректно PropTypes проверка работает только в dev, но если вы что то сделали не так то оно и не заведется
                                                с промисами согласен, но пока особенно не мешало
                                                • +2
                                                  1, 2 во многом решает webstorm


                                                  Да не возможно это так же качественно сделать как в ts.
                                                  • 0

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

                                                    • 0
                                                      я пишу не только react.js но и react native, хоть пример mayorovp выглядит очень разумно, но до версии rn 1.0 ts точно использовать не буду ) а вот для react.js нужно будет попробовать
                                                    • +1

                                                      Знает ли webstorm что когда вы пишите, условно, foo.addEventListener("bar", e => e.|); какие будут свойства у параметра e? А если знает, то что делать с более сложным случаем?


                                                      mobx.observe(foo, e => {
                                                          if (e.type == "update") {
                                                               e. // 1
                                                          }
                                                          if (e.type == "splice") {
                                                               e. // 2
                                                          }
                                                      });

                                                      Знает ли webstorm что в точках (1) и (2) будут разные списки доступных свойств?

                                                      • 0
                                                        спасибо, подобных примеров я и ждал
                                                        • 0
                                                          Можно для более строгой типизации ещё немного доработать:

                                                          mobx.observe(foo, e => {
                                                              if (e.type == "update") {
                                                                   (e as update). // 1
                                                                   // Либо
                                                                  (<update>e). // 1
                                                              }
                                                              if (e.type == "splice") {
                                                                   (e as splice). // 2
                                                                   // Либо
                                                                  (<splice>e). // 2
                                                              }
                                                          });

                                                          Понятно, что для JSX подходит только первый вариант, т.е. as-синтаксис.
                                                          • 0

                                                            Но зачем писать лишний код когда компилятор и так все понимает?! Кстати, не update и splice — а IArrayChange<T> и ArraySplice<T>, причем тип T еще нужно где-то найти...

                                                            • 0
                                                              Да, согласен, написал не в тему, поспешил (людей насмешил).
                                                              Не разглядел mobx, т.к. с mobx не пересекался. Подумал, что в свойстве e.type хранится тип самого объекта e, т.е. update и splice — суть возможные типы объекта e. Соответственно, конструкции: (e as update). и (e as splice). помогут webstorm знать в точках (1) и (2) списки доступных свойств.
                                                        • 0
                                                          3 не совсем корректно PropTypes проверка работает только в dev

                                                          А если мы хотим один из этих пропсов передать во внешнюю функцию? Ну типа того же mapReplace, что повыше. Вы как будете пропТайпами типизировать?
                                                          Зачем этот сломанный костыль, если есть адекватное решение, которое работает на всем коде, а не только там, где повезет?
                                                      • 0

                                                        Как минимум это спасает от опечаток — в js (с бабел и вебпак) код скопмилится и сломается в рантайме — с typescript-ом просто не скомпилиться

                                                      • –4
                                                        В общем, TS хорош тем, что он новый. И плох тем же.
                                                        • +3

                                                          Месяц назад день рождения праздновал. 5 лет. По меркам фронтенда это долгожитель.

                                                        • 0
                                                          А пробовали обновлять инструменты, которые используете, проект стартует? Не задумывались о том, что когда придет время переходить на более свежие версии, то придется много чего переписать, выкинуть и перенастроить окружение полностью?
                                                          • 0
                                                            Конечно задумывались, и обновляли, и страдали и иногда дорого.
                                                            Иногда даже не обновляешь версии, а в пн бах — и уже не собирается, потому что где-то косвенная зависимость нестрого: ^0.1.1 версию тянет и все, как было недавно с babel-transform-generator (если не изменяет память). Npm-Shrinkwrap нас спасет!
                                                            • 0

                                                              А вы собираетесь обновлять окружение? Или этот проект отработает отведенное ему время, а потом просто перепишите все с нуля?

                                                              • 0
                                                                Обновляем окружение, где-то просто и это делается по факту. Где-то оцениваем стоимость перехода и профит. В планах-задачах все это есть: поднимать react, react-router, typescript и пр.
                                                        • –2
                                                          Идеология TypeScript в корне противоречит функциональному подходу принятому в React и использовать их в такой связке неверно.
                                                          Жаль, что про Flow вы не знали, впрочем сейчас ReasonML набирает обороты (это то, что может стать стандартом в будущем).
                                                          TypeScript хорош с Angular и только там ему место
                                                          • 0
                                                            Идеология TypeScript в корне противоречит функциональному подходу принятому в React и использовать их в такой связке неверно.

                                                            Псевдо-функциональный подход принят исключительно в Редаксе. Реакт — вполне себе мультипарадигменный и даже больше ООПшный, чем ФПшный. Мы его использует с TS и MobX, и не знаем бед — у нас ВСЕ статически-типизированно, никакого сомнительного кода.
                                                            • +2
                                                              > Идеология TypeScript в корне противоречит функциональному подходу принятому в React и использовать их в такой связке неверно.
                                                              > Жаль, что про Flow вы не знали

                                                              Видимо, вы про Flow тоже не в курсе, иначе бы знали, что он от Typescript, в плане поддержки функциональных подходов, не отличается.

                                                              > впрочем сейчас ReasonML набирает обороты (это то, что может стать стандартом в будущем)

                                                              Не станет, т.к. фейсбук _очень_ плохо в типах разбираются, что flow показал. Тут надежды как раз на мелкомягких, они себя уже очень хорошо в этой области зарекомендовали — как в чисто теоретических рокет-саенс разработках, так и в доведении их до практики. Фактически, они последнее десятилетие тут локомотив прогресса и законодатели мод.
                                                              • –3
                                                                Видимо, вы про Flow тоже не в курсе, иначе бы знали, что он от Typescript, в плане поддержки функциональных подходов, не отличается.

                                                                Flow это не столько язык, сколько Type cheker, для чего и создавался, поэтому неправильно говорить, что он не отличим от TypeScript. Это просто разные вещи. TypeScript — же это мощной язык, агрессивно насаждающий ООП, там где это не нужно.
                                                                Не станет, т.к. фейсбук _очень_ плохо в типах разбираются, что flow показал

                                                                Наивно так утверждать, хотя согласен, что Microsoft хорош в развитии языков.

                                                                Моя критика относится к людям которые пытаются скрещивать ужа с ежом (TypeScript и React). Не думаю, что Microsoft ставила такую задачу, думаю Microsoft как раз понимают, что делают, в отличие от некоторых фронтендеров
                                                                • +1
                                                                  > Flow это не столько язык, сколько Type cheker

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

                                                                  > Моя критика относится к людям которые пытаются скрещивать ужа с ежом (TypeScript и React). Не думаю, что Microsoft ставила такую задачу

                                                                  Вы не поверите — но ставила. Задача, которая ставилась перед системой типов TS — максимально простая и безболезненная типизация существующих JS-идиом (в том числе и тех, что используются в реакте или редаксе или еще где — оно ведь на JS), пусть и в ущерб soundness (сам факт наличия TSX, кстати, говорит о том, что и отдельная задача совместимости с реактом существовала в явном виде).
                                                                  Система типов Flow, с другой стороны, дизайнилась в первую очередь с расчетом на soundness, пусть и ценой дополнительных трудностей в выражении типов для существующего кода.
                                                                  Собственно, это и есть единственное важное отличие Flow от TS, все остальное — просто следствия этой разницы на уровне идеологии.
                                                                  • –1
                                                                    Flow — это вполне отдельный язык, точно так же, как TypeScript, прошу, не повторяйте буллшит, которым кормят маркетологи фейсбука

                                                                    здесь не я повторяю буллшит, а вы пытаетесь додумывать за фейсбук
                                                                    сам факт наличия TSX, кстати, говорит о том, что и отдельная задача совместимости с реактом существовала в явном виде

                                                                    JSX это не весь React, и создание TSX ни о чём не говорит
                                                                    • +1
                                                                      > а вы пытаетесь додумывать за фейсбук

                                                                      Додумывать что?

                                                                      > JSX это не весь React, и создание TSX ни о чём не говорит

                                                                      Создание TSX говорит о том, что взаимодействие ТС и реакта было отдельной, четко обозначенной задачей. Которая ставилась. Если бы такая задача не ставилась — TSX бы не существовало.
                                                                    • 0
                                                                      Что вы понимаете под soundness?
                                                            • 0
                                                              могу посоветовать интересный доклад Ильи Климова с конференции HolyJS 2017 Piter, где он сравнивает TypeScript и Flow

                                                              Вот он https://youtu.be/etKOc80-cw0
                                                              • 0
                                                                Устройте открытое бесплатное обучение TypeScript. Уверенна, что подтянутся толковые люди как из компании, желающие переквалифицироваться, так и снаружи. К счастью, PR Сбертеха позволяет привлечь хорошую аудиторию на такие курсы.

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

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