🔥

Тред (Антон Кастрицкий)


Вчера большинство проголосовало за сравнение статических систем типов, поэтому поехали 👇👇👇

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

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

Для начала про типы в целом, там где они не влияют на рантайм и вырезаются при сборки, алгоритм их использования должен быть примерно такой
notion image

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

На изображении видно как жёлтый немного просачивается в зелёную зону, в системах типов есть баги, про них нужно знать. Такое бывает, жизнь случается ¯_(ツ)_/¯

Мне бы хотелось устроить большое сравнение и втащить сюда sound elm, purescript с его коммюнити академических фетишистов, reason или bucklescript или rescript, ладно сдаюсь, поэтому сегодня будет только flow и typescript

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

Цель flow - быть sound type system. Если флоу говорит не ругается, то TypeError не может случится. Это так же означает что возможны false positive, то есть флоу может ругаться на те места где по бизнесс логике ошибки не может случится

Цель TS - быть complete type system. Другими словами команда тайпскрипта пытается найти баланс между достижением type safety и продуктивной работы разработчика. Это 3ий пункт в их публичных не целях. github.com/Microsoft/Type…

Это значит что всё что TS помечает ошибкой, действительно ошибка, но могут быть false negative - намеренно пропущенные потенциальные ошибки

Жду дня, когда буду находиться на встрече по разбору инцидентов из прода - Антон, почему у нас тогда прод сломался Мы потеряли миллионы - Просто мне было удобно писать на TS 🤗

Дальше про отличия: Flow - только аннотации типов, которые никак не влияют на рантайм TS - отдельный язык, который помимо типов так же добавляет свои runtime конструкции вроде enums, decorators, parameter properties etc

Тут же нужно отметить что typescript состоит из 2ух инструментов - тайпчекер для проверки типов - компилятор который превращает код из ts в js

Далее можно кучу всего написать про отдельные отличия как flow с номинальной+струтурной vs только структурной типизацией у ts, наличие const assertions и прочие, но это скорее всего будет не интересно. Поэтому следующая пачка будет про вещи на которых можно больно спотыкаться😩

Флоу позволяет спредить типы объектов для того что бы мержить их между собой, пайпы используются для обозначения строгих объектов, интерсекшенами (&) мы почти не пользовались
notion image

В TS нет спредов, но поэтому давайте интерсектить, но можно доинстрсектится и получить never, потому что нет сегодня значения удовлетворяющего string & boolean, во флоу проблема будет похожа
notion image

Если хотим узнавать об ошибках коллизии ключей при написании, то начинаем смотреть в сторону интерфейсов вместо тайп алиасов
notion image

Если же нам нужен аналог мержа, то пишем небольшой утил
notion image

Для undefined во флоу есть void, в тс есть два типа void и undefined. Между ними есть отличия void для определения чегото чем не нужно пользоваться undefined - валидное значение
notion image

This Флоу пытается самостоятельно вывести тип this в зависимости от контекста, а в ts вы можете явно его указать назвав первый аргумент функции this. Надеюсь что это нигде и никому никогда не понадобится, кроме серверного кода яндекс маркета😅
notion image

Про any vs unknown / mixed расписывать не буду Видите any? Удаляйте, ставте mixed(flow)/unknown(ts) - нервы дороже, пишите явные проверки

Стоит отметить что документация у этих инструментов очень хороша typescript - читаешь и можнешь просто писать на этом языке flow - прочитал как книжку и +200 к iq, понимаешь про устройство систем типов, вариативность типов, но как flow пользоваться нужно еще разобраться

Сужение типов aka type refinement aka type narrowing Не вижу смысла дублировать документацию, поэтому если вам не очевидно почему на картинке в первом условии тип не сужается, а во стором сужается, то вот две ссылки flow.org/en/docs/lang/r… typescriptlang.org/docs/handbook/…
notion image

Если бы мне давали 1$ за каждый раз когда у меня спрашивают почему оно так
notion image

Далее type guards / type predicates Писать проверки прямо в условиях не удобно и хочется их переиспользовать, это умеют оба языка. Вот флоу
notion image

А вот тайпскрипт, обращаем внимание что синтаксис нам позволяет явно указать что мы проврям что аргумент это строка
notion image

С гардами нужно быть аккуратным, ведь случайно можно написать не ту проверку и тогда флоу перестанет сужать тип
notion image

В случае с тайпскриптом ему всё равно что вы там проверяете и типы будут продолжать сужаться, поэтому считаю это настоящим револьвером для отстреливания нижних конечностей Если можете заинлайнить проверку в условие - такбудет безопасней ✅
notion image

В ts еще есть assert type guard'ы, удобная штука, если вам нужно заассертить какое то значение, но она наследует все те же проблемы обычных гардов, имейте введу
notion image

уф, а про саппрешены ведь не написал, можно игнорировать ошибки, все саппрешн комментарии($FlowFixMe) во флоу будут помечаться как ворнинги или с флагом в конфиге ошибками и вы в любом случае узнаете о том что есть неиспользуемые сапрешены, которые не игнорируют ни-че-го

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

В 3.9 появился [@ts](https://twitter.com/ts)-expect-error который сообщит вам если он является лишним, предлагаю всключить estlint правило и запретить [@ts](https://twitter.com/ts)-ignore в принципе github.com/typescript-esl…

Еще одна опасная* фича TS это null assertions, когда у вас есть nullable значение, но вы знаете лучше компилятора что там не null и просите его проигнорировать ваше отсутствие проверки. Имхо лучше эту фичу запретить линтером, вот и правило github.com/typescript-esl…
notion image

Еще немного поною про тайпскрипт и пойдут его плюсы

Используй тайпскрипт говорили они, там строгие объекты говорили они
notion image
notion image

Туда же и массивы
notion image

Из остального ts нытья: - отсутствие opaque типов - если у вас дженерик функция, вы не можете передать один из ниескольких джинериков, если начали предавать, то передавайте всё остальные тоже

и еще чуть чуть - дженерики с условиями 👉 <T extends Foo> ts относится T теперь ковариант, должен быть как Foo, но может содержать его расширять - отсутствие инвалидации сужения типов - отсутвие $Call, есть ReturnType и infer, но блин не то🙂

Как можно догадаться мне было сложно перейти на ts, но в какой то момент я понял что мои интересы расходятся с интересами команды тайпскрипта и это ок. Это нужно принять и жить с этим ¯_(ツ)_/¯ Дальше про плюсы TS

Жирнейший плюс это распространенность, почти на всё уже есть тайпинги если не в самой бибилотеке то в DefinitelyTyped

У TS есть поддержка JSDoc, не только как для описания типов, но и как документация к типам/функциям и тд, оно прорастает в хинты в редакторах 🤗
notion image

Наличие шаблонных строковых типов позволяет творить интересные вещи, например парсить джейсон не запуская джаваскрипт (ради бога не используйте это, фича крутая, библотека для пример) github.com/jamiebuilds/js…

Если у вас redux, но не redux-toolkit, то может понравиться вот это github.com/antonk52/rainb…

в целом "интегрированность" в современные инструменты у TS на высоте, это всегда было слабой чертой flow

В целом на этом можно сворачивать тему человека с мечтами о soundness, но пишущего на javascript

Забыл про что то? Вы хотели ухлышать про Х, но этого не было? Что пропустил?

Забыл интересные факты, например тайпскрипт не следует семверу github.com/microsoft/Type… github.com/microsoft/Type…