saitonakamura

27 января 2020, Earth Planet

# Понедельник 19 твитов

Йоу! Под конец января с вами Майк Башуров @SaitoNakamura. Много лет делал .NET, ушел во фронтенд и не жалею. Будем… twitter.com/i/web/status/1…

10:08

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

10:08

Начнем с начала тайпскрипта, то бишь с его прошлого

Появился он еще в 2012 году zdnet.com/article/micros…
, релиз 1.… twitter.com/i/web/status/1…

10:43

В то время язык был местами ближе к C# чем к JS, отсюда namespaces, classes, private/public/protected.

В целом эт… twitter.com/i/web/status/1…

10:43

Итак на дворе 2012, Путин возвращется на президенское кресло после Медведева, до ES2015 еще три года (я кстати снач… twitter.com/i/web/status/1…

10:43

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

10:55
@jsunderhood И кошмар с .d.ts
Пока не появился и не стал популярен Angular пользоваться Typescript было больно име… twitter.com/i/web/status/1…
11:00

Несмотря на то что в языке сразу были namespaces, назывались они в начале modules. Естественно это вызвало name cla… twitter.com/i/web/status/1…

11:15

Вообще на релизе в ТС не было очень многого чем мы с вами пользуемся сейчас. Даже если не считать фичи ES2015 до TS… twitter.com/i/web/status/1…

11:20
@jsunderhood Для большинства библиотек их не было. Но это было не так страшно, как то, что они устаревали и сильно… twitter.com/i/web/status/1…
11:26
@jsunderhood Сейчас открыл фронтенд-проект 2013 года на angularjs/typescript и я не вижу тут ничего про npm все typ… twitter.com/i/web/status/1…
11:26
@musuk Ах да, раньше была утилита typings github.com/typings/typings которая устанавливала тайпинги прямо в репу (такж… twitter.com/i/web/status/1…
11:28
@musuk Я бы кстати не сказал что тот или другой подход обязательно плохой и обернется болью

Чем меньше и хуже каче… twitter.com/i/web/status/1…

11:28
@musuk Но если вы захотите исправить именно исходник (например чтобы потом сделать PR) будет очень неудобно, потому… twitter.com/i/web/status/1…
11:29

Но 2.0 превнес наиважнейшую фичу: nullable types. Возможность сказать: "Вот здесь будет точно string/number/какой-т… twitter.com/i/web/status/1…

11:33

Многие современные языки
* являются функциональными языками с монадой Maybe (Haskell, Scala, F#, OCaml, ReasonML)
*… twitter.com/i/web/status/1…

11:42

Если кому интересно, работаю я в WiseBits, Лимассол, Кипр (недавно переехал), буду тут делать комьюнити, а также я… twitter.com/i/web/status/1…

12:33

Про монадки и прочее фп мы поговорим попозже, а пока вернемся к истории

Вообще, если хочется тщательно проследить… twitter.com/i/web/status/1…

12:36
@musuk @jsunderhood тоже примерно в те годы исползовал angularjs + typescript. не сказал бы что было как-то больно… twitter.com/i/web/status/1…
12:54

# Вторник 41 твит

Извиняюсь за перерыв, работать тоже надо (как ни странно)

Продолжаем

В 2.0 также появилась опция --skipLibCheck.… twitter.com/i/web/status/1…

16:38

Варианты действий при ошибке компиляции в тайпингах

Идеальный: форкнуть существующие тайпинги, поправить ошибку, с… twitter.com/i/web/status/1…

16:44

Дело просто в том что иногда такие ошибки возникают при апгрейде версии самого ТС, а времени делать целый PR нет

В… twitter.com/i/web/status/1…

16:44
@jsunderhood Есть ещё один минус TS: copypastablilty со stackvoerflow и из документации к либам хромает.
Там скорее… twitter.com/i/web/status/1…
16:47
@musuk Я бы не сказал что прям хромает, большинство жс кода тс проглотит, хоть и с ругательствами

К тому же есть в… twitter.com/i/web/status/1…

16:47
@musuk @jsunderhood Кмк это и минус и плюс. Адаптировать любой код в типы с оверфлоу легко. Так что бонус и для жс и для тс.
16:48
@jsunderhood @musuk Можно ещё прочитать twitter.com/johnny_reilly/…

Отличное чтиво!

@jsunderhood @musuk Можно ещё прочитать twitter.com/johnny_reilly/…

16:48

В 2.1 появился исключительно полезный типооператор keyof. На нем строится наверное процентов 80 (люди склонны вери… twitter.com/i/web/status/1…

17:03

И вы хотите его типизировать, но не просто icon: string, а чтобы можно было только plus и menu

Конечно можно напис… twitter.com/i/web/status/1…

17:03

Но можно просто написать keyof typeof svg и он автоматом возьмет все свойства svg!

Самое полезное здесь конечно то… twitter.com/i/web/status/1…

17:03

Подробнее про keyof здесь
typescriptlang.org/docs/handbook/…

Из минусов (на самом деле скорее особенностей): keyof работает т… twitter.com/i/web/status/1…

17:06

Наверное стоит еще остановиться на typeof раз уж я его упомянул

Дело в том что для ТС при парсинге и компиляции су… twitter.com/i/web/status/1…

17:14

Так как типов в рантайме нет (об этом мы с вами еще поговорим), то влиять на рантайм как бы нельзя

Но вот с помощь… twitter.com/i/web/status/1…

17:14

Таким образом

const svg = {
plus: './plus.svg',
menu: './menu.svg
}

type Svg = typeof svg
// { plus: string;… twitter.com/i/web/status/1…

17:19

Лирическое отступление лирического отступления:
Особо пытливые заметили что typeof является правоассоциативным опер… twitter.com/i/web/status/1…

17:19

Возвращаемся на землю (нет, не плоскую)

Еще в 2.1 появились mapped types. Это вторая основа тайплевела который мож… twitter.com/i/web/status/1…

17:26

И наконец опция с путающим названием --alwaysStrict
Она непохожа на остальные опции семейства --strict (strictNulla… twitter.com/i/web/status/1…

17:26
@jsunderhood Можно не ждать, кстати, пока фикс вольют, а добавить в репу пофикшенный файл с тайпингами (см. typesRo… twitter.com/i/web/status/1…
17:36
@timocov_ Все так!

Я просто говорил не про тот случай когда типов недостает или они немного неправильные, а когда… twitter.com/i/web/status/1…

17:38

В 2.3 появилась важная опция --strict
Она включают кучу других опций которые делают ваши типы строже и правильней… twitter.com/i/web/status/1…

17:41
@jsunderhood Стоит сказать, что сейчас с этим проще, поскольку все (или почти) тайпинги обновляют под новые версии… twitter.com/i/web/status/1…
17:48
@timocov_ Да, я где-то видел как при breaking changes кор контрибьюторы писали codemodes для definitely typed и про… twitter.com/i/web/status/1…
17:48
@timocov_ А поводу несовместимости: если реально несовместимы то беда конечно

Я не призываю использовать --skipLib… twitter.com/i/web/status/1…

17:48

Следующим экспонатом (мы видимо в историческом музее) версии 2.3 будет --checkJs

Совместно с JSDoc это то на чем с… twitter.com/i/web/status/1…

17:53

В 2.4 завезли string enums

enum Colors {
Red = "RED",
Green = "GREEN",
Blue = "BLUE",
}

Несмотря на и… twitter.com/i/web/status/1…

17:56

В 2.6 добавили страшно желаемую фичу // @ts-ignore
Если где-то есть ошибка и вы хотите заткнуть компилятор, но испо… twitter.com/i/web/status/1…

18:00
@musuk @jsunderhood Не так уж все плохо.

Скопировал код, нажал “infer types from usage” в редакторе, получаешь впо… twitter.com/i/web/status/1…

19:05
@theKashey @boriscoder @musuk tsserver такое представляет в качестве code action pic.twitter.com/vA4guq1EVD
19:43
@jsunderhood Мы наоборот перешли на них, т.к. важность порядка при синке с бэками — неудобно

Вполне валидный кейс

@jsunderhood Мы наоборот перешли на них, т.к. важность порядка при синке с бэками — неудобно

19:52
@jsunderhood @boriscoder @musuk Немного усложню ваш пример. Применив автоматическое извлечение типов, мы получим… twitter.com/i/web/status/1…
20:50
@neruchev @boriscoder @musuk Ммм, пример не очень корректный ибо вы здесь примешиваете проблему отсутствия нормальн… twitter.com/i/web/status/1…
20:50
@neruchev @boriscoder @musuk Если же вы выразите ваш Value через костыльными номинальные типы (в ТС прижилось назва… twitter.com/i/web/status/1…
20:51
@jsunderhood Еще валидный кейс: когда надо разделить внутреннее преставление от внешнего красивого апи.
Например: e… twitter.com/i/web/status/1…
20:53
@MrFlashAccount а вот это уже вполне можно решить обычным объектом

const Colors = {
RED: 'var(--color-red)'
}

20:54
@jsunderhood @boriscoder @musuk В больших и сложных проектах такие мелочи могут очень больно ударить, ловили не раз.

Я вообще буду рад если вы (аудитория) будете делиться болью
Обсудим, может даже что-то порешаем, на крайняк посидим… twitter.com/i/web/status/1…

@jsunderhood @boriscoder @musuk В больших и сложных проектах такие мелочи могут очень больно ударить, ловили не раз.

20:57
@jsunderhood @boriscoder @musuk Спасибо, не знал что так можно!
Хотя действительно выглядит слегка костыльно (и не вполне очевидно).
21:08
@neruchev @boriscoder @musuk В целом если объяснить это команде то жить с этим вполне можно (если бенефиты оправдыв… twitter.com/i/web/status/1…
21:09
@jsunderhood @boriscoder @musuk К счастью тред не про флоу, от кашляющих щас лучше бежать :D
21:15

На сегодня наверное все, завтра добьем историю и поддадим хардкору

21:17
@jsunderhood Вот это кстати очень "боль". Имею в виду "обьяснить команде". Тяжело это. Большинство, чаще всего прот… twitter.com/i/web/status/1…

Поддерживаю
Я не виню в этом людей, но коммуникация сложная даже если ты не пытаешься что-то продать

@jsunderhood Вот это кстати очень "боль". Имею в виду "обьяснить команде". Тяжело это. Большинство, чаще всего прот… twitter.com/i/web/status/1…

21:19

Я как раз неделю назад занимался тем что продавал всякую продвинутую типизацию (сам ТС команде уже продали до меня… twitter.com/i/web/status/1…

21:21

# Среда 67 твитов

@jsunderhood Хардкор - это прикручивать TypeScript к существующему JS проекту.

И в самом деле, впиливать в уже существуюший проект (особенно большой) гораздо сложнее
Но у меня больше проблем не… twitter.com/i/web/status/1…

@jsunderhood Хардкор - это прикручивать TypeScript к существующему JS проекту.

9:28
@jsunderhood @ts Типы сложные, а релизить надо вчера :D

Да, несмотря на то что конечно надо стремиться к отсутствию авралов и СРОЧНА НАДА, без этого никуда

@jsunderhood @ts Типы сложные, а релизить надо вчера :D

9:32
@jsunderhood Некогда описывать сложные типы. Приходится писать "any".
9:34
@SN__PR А сложные это какие в вашем случае?

Сложные манипуляции с типами (mapped, conditional types) или куча разных полей с бэкенда?

9:34
@jsunderhood Сложные в моём случае === не примитивные (string, boolean, number)
10:01
@SN__PR Опять же вопрос к авралам:

Если времени не хватает постоянно (чтобы разобраться) то бороться надо прежде в… twitter.com/i/web/status/1…

10:01

Дело в чем. Раньше когда вы не знали что будет за тип, был один выход: any
any плох тем что с ним можно делать что… twitter.com/i/web/status/1…

10:20

А с unknown вы сначала должны доказать компилятору что он не пустой, в нем есть такое поле и оно такого-то типа и… twitter.com/i/web/status/1…

10:20

Для того чтобы доказать используются type refinements (они же type guards)
Выглядеть может примерно так

Можете пои… twitter.com/i/web/status/1…

10:33

Но если вот такие type guards работают не очень, то что делать?

Ответ: user-defined type guards

Поиграться… twitter.com/i/web/status/1…

10:39

Проблемы с ними две

  1. Как видите надо много писать

  2. Имплементация лежит исключительно на вас
    То есть можно нап… twitter.com/i/web/status/1…

    10:41
@jsunderhood Боль - unsoundness, ограниченный вывод типов по call site - много печатать тайпингов. Но это все by de… twitter.com/i/web/status/1…

Да, полностью согласен

Но у меня есть туз в рукаве

@jsunderhood Боль - unsoundness, ограниченный вывод типов по call site - много печатать тайпингов. Но это все by de… twitter.com/i/web/status/1…

10:42

Тем не менее само наличие unknown уже заставляет задуматься об избыточном использовании any, что не может не влиять… twitter.com/i/web/status/1…

10:44
@timocov_ Да, я где-то видел как при breaking changes кор контрибьюторы писали codemodes для definitely typed и про… twitter.com/i/web/status/1…

В 3.1 как раз появилась возможность указывать разные версии тайпингов для разных версий компилятора… twitter.com/i/web/status/1…

@timocov_ Да, я где-то видел как при breaking changes кор контрибьюторы писали codemodes для definitely typed и про… twitter.com/i/web/status/1…

10:46

В 3.4 появилась наикрутейшая возможность const assertions, например

Раньше когда у вас была функция которая возвра… twitter.com/i/web/status/1…

10:55

Характерный пример это action creators в редаксе

const createLoad = () => ({
type: 'LOAD'
})

type LoadAction =… twitter.com/i/web/status/1…

10:55

Ну казалось бы стринг и стринг, что такого то

А такого то, что еще есть такая штука как discriminated unions котор… twitter.com/i/web/status/1…

10:55

И для того чтобы они (discriminated unions) работали надо чтобы type был string literal, а не просто string

То ест… twitter.com/i/web/status/1…

11:01

type widening это когда в результате некоторых манипуляций тип становиться менее строгим

вот мы возращаем в нашем… twitter.com/i/web/status/1…

11:01

Поэтому ему надо подсказать что литерал будет иммутабельный

const createLoadAction = () => ({
type: 'LOAD'
} as… twitter.com/i/web/status/1…

11:01

as const работает не только на объектных литералах но и на обычных

то есть можно написать

const createLoadAction… twitter.com/i/web/status/1…

11:03
@jsunderhood

Как ты считаешь, чем лучше транспилировать ts?

Траспилить бабелем, тайпчек отдельно

Несмотря на то что официально майки рекомендуют траспилить через tsc, бабель… twitter.com/i/web/status/1…

@jsunderhood

Как ты считаешь, чем лучше транспилировать ts?

11:05

В 3.5 наконец-то добавили хелпер Omit в стандартную поставку

В 3.6 нормально затипизировали генераторы
typescriptlang.org/docs/handbook/…

11:11

В 3.7 в срочном порядке добавили поддержку nullish coalescing и optional chaining (причем прямо с 3-его стейджа ЕМН… twitter.com/i/web/status/1…

11:11

Assertion function это история про exception flow control

То есть проверили предусловия контракта и пошли дальше п… twitter.com/i/web/status/1…

11:11

Еще в 3.6 пофиксили некоторые рекурсивные типы
typescriptlang.org/docs/handbook/…

Раньше можно было делать рекурсивные типы к… twitter.com/i/web/status/1…

11:16

Короче вот так было можно

type Tree<T> = {
value: T,
children: Tree<T>[]
}

а вот так вот нельзя

type Json =… twitter.com/i/web/status/1…

11:16

Кстати до 3.6 был интересный хак чтобы обходить такое

Дело в том что по стечению обстоятельств type вычисляется ea… twitter.com/i/web/status/1…

11:18

type Json =
| string
| number
| boolean
| null
| JsonObject
| JsonArray;

interface JsonObj… twitter.com/i/web/status/1…

11:18
If you’re wondering a bit about what the use-case for `import type` is used for in @typescript 3.8 - one of it’s ma… twitter.com/i/web/status/1…

В 3.8 нас главным образом ожидают очередные новые фичи ECMAScript (например top-level await), но самая мякотка в ty… twitter.com/i/web/status/1…

If you’re wondering a bit about what the use-case for `import type` is used for in @typescript 3.8 - one of it’s ma… twitter.com/i/web/status/1…

11:23

Ну вот и все про историю!

Пойду поработаю, следующий тред будет про то как я вижу идеальный проект на ТС

11:25
@jsunderhood Для себя в последнее время открыл ttsc - кастомная обертка, которая поддерживает плагины. Позволяет из… twitter.com/i/web/status/1…

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

1 В целом tsc п… twitter.com/i/web/status/1…

@jsunderhood Для себя в последнее время открыл ttsc - кастомная обертка, которая поддерживает плагины. Позволяет из… twitter.com/i/web/status/1…

12:06
@timocov_ @konstantin6487 @jsunderhood Для этого существуют соурсмапы. Ну и транспилить можно в es2015, тогда код остаётся читаемым
19:56
@jsunderhood Я бы наоборот не рекомендовал использовать бабель от слова совсем. Тот код, который он генерит читать потом невозможно.
19:56
@timocov_ Не сказал бы что имея один и тот же таргет как-то сильно отличается эмит

Классы у обоих не сразу понятны… twitter.com/i/web/status/1…

19:56
@jsunderhood Разве это больше про иммутабельность чем про сужение типов, т.е. выключение type widening?
19:59
@timocov_ Это не больше и меньше, это две половинки одного целого

Если бы не было мутабельности, не нужен бы был t… twitter.com/i/web/status/1…

19:59
@jsunderhood Кстати интересно, почему они решили добавить новый синтаксис, вместо того, чтобы заюзать старый с "пер… twitter.com/i/web/status/1…
20:02
@timocov_ Потому что never это сильно больше чем бросить ошибку (особенно с точки зрения теории типов)

never это т… twitter.com/i/web/status/1…

20:02
@jsunderhood Мне кажется, что экосистема не развита как раз из-за того, что нет нормального способа эти плагины юзать.
20:03
@timocov_ Так и есть, и то что они не открывают удобное апи плагиноке - это сознательное решение

Потому что иначе… twitter.com/i/web/status/1…

20:03
@jsunderhood Самая большая боль пока — это вывод ошибок в сложных типах

Дико поддержу

Кто-то где-то сказал что у статической типизации ужасный UX

И это правда так, типы обычно не говоря… twitter.com/i/web/status/1…

@jsunderhood Самая большая боль пока — это вывод ошибок в сложных типах

20:07

Следующий тред про то как я вижу идеальный проект на ТС (и почему, естественно)

Как будто нам дали требования и мы… twitter.com/i/web/status/1…

20:15

Первым делом установили npm i -D typescript
И инициализировали конфигурацию npx tsc --init
Дефолты на данный момент… twitter.com/i/web/status/1…

20:16

На esModuleInterop остановимся поподробнее

Опция появилась в 2.7 и помогла сделать поведение импортов консистентым… twitter.com/i/web/status/1…

20:23

Против import React from 'react' у бабеля

Реальность показала что прав был бабель: * as React это namespace impor… twitter.com/i/web/status/1…

20:23

Кто хочет подробно разобраться в теме: я в свое время накатал объемную статью (осторожно, Инглиш)… twitter.com/i/web/status/1…

20:23
@timocov_ @jsunderhood loose preset же есть. В нем babel тоже Class.protype.method генерирует babeljs.io/repl/#?browser…
20:24

Окей, с модулями разобрались, все стрикты врубили, что дальше

Дальше стоит определиться с тем какие фичи языка исп… twitter.com/i/web/status/1…

20:29

Почти все фичи которых нет хотя бы на stage 4 были введены довольно давно

Большинство новых фич не относящихся с E… twitter.com/i/web/status/1…

20:29
В 2.4 завезли string enums

enum Colors {
Red = "RED",
Green = "GREEN",
Blue = "BLUE",
}

Несмотря на и… twitter.com/i/web/status/1…

namespaces уже совсем мало кому нужны, не вижу смысла на них останавливаться

стоит однако заметить что в тайпингах… twitter.com/i/web/status/1…

В 2.4 завезли string enums

enum Colors {
Red = "RED",
Green = "GREEN",
Blue = "BLUE",
}

Несмотря на и… twitter.com/i/web/status/1…

20:34

Начнем с того что енамов в ТС 4 вида
enum, const enum, declare enum и declare const enum

Все они имеют некоторые о… twitter.com/i/web/status/1…

20:41

Извиняюсь, 6 там не к месту (но и без нее непросто)

В третьих помните я говорил чтобы получить тип от рантаймового… twitter.com/i/web/status/1…

20:43

Стоит ли также упомянуть что enum врядли станет когда-нибудь частью стандарта?

И при всем при этом абсолютное боль… twitter.com/i/web/status/1…

20:51

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

en… twitter.com/i/web/status/1…

20:51

если же у вас есть какое-то апи завязанное на строки, к примеру

enum RequestType {
GET: 'GET'
POST: 'POST'
}… twitter.com/i/web/status/1…

20:51

С вышеназванными кейсами видимо понятно, так когда же енам все еще полезен?

1 Чтобы 1в1 скопировать енамы с бэка и… twitter.com/i/web/status/1…

20:58

2 Для придавания семантики числовым опциям. Этим опять же может грешить бэк и принимать вместо строковых ключей - ч… twitter.com/i/web/status/1…

20:58

Ладно, енамы, что еще?

Декораторы! С ними... Сложно.

Мне как фича языка они нравятся, НО

Есть ощущение (может кт… twitter.com/i/web/status/1…

21:12

И декораторы уже кажется два раза падали с stage 3 на stage 2 с ломающими изменениями

В итоге состояние декторатор… twitter.com/i/web/status/1…

21:12

Во-первых декораторы не могут влиять на типы декорируемой сущности

поэтому написать

@connect(mapStateToProps)
con… twitter.com/i/web/status/1…

21:12

В итоге при использовании компонент потребует лишние пропсы

Можно конечно написать кучу явных приведений, но это т… twitter.com/i/web/status/1…

21:12
@jsunderhood Прям как класс!

Нуу кстати, да, это я зафейлил, сорян

@jsunderhood Прям как класс!

21:13

Но если уж инвестируете в декораторы (например Nest) то еще есть reflect-metadata

Это вот уж точно чисто для ангул… twitter.com/i/web/status/1…

21:20

Несмотря на то что фича довольно крутая, меня очень смущает то что ее никто кроме Анга не использует

Но судя по вс… twitter.com/i/web/status/1…

21:20

Со старыми фичами разобрались, про остальное продолжим завтра

Stay tuned

21:21
@jsunderhood @rm_baad @HolyJSconf typegraphql.ml очень активно используют
21:55

# Четверг 30 твитов

@jsunderhood Декораторы ни разу не поднимались на stage 3

Меня поправляют

@jsunderhood Декораторы ни разу не поднимались на stage 3

6:41
@jsunderhood Декораторы в нынешнем виде пришли из-за Google, который делал своё надмножество TypeScript, называемое… twitter.com/i/web/status/1…
6:42
@jsunderhood Ещё inversify есть, typeorm, typegoose и прочая куча пакетов для ORM и IoC.

Оказалось что на самом деле reflect-metadata использует много кто!

Я думал что всякие inversify живут на строковых… twitter.com/i/web/status/1…

@jsunderhood Ещё inversify есть, typeorm, typegoose и прочая куча пакетов для ORM и IoC.

7:17
@jsunderhood @ts Хороший кейс для ts-ignore, правда это скорее vscode-ignore pic.twitter.com/QfNl7Pd3AX
7:20
@jsunderhood @ts Для понимания: проблема в том, что нет определения модуля semantic-ui-css. Оно и не нужно, ведь эт… twitter.com/i/web/status/1…
7:20
@notorious_js @ts Вообще для таких случаев можно сделать global.d.ts

declare module "*.css" {
const content: str… twitter.com/i/web/status/1…

7:20
@jsunderhood полагаешься на выведение типов, или пишешь их всегда явно, даже если они корректно выводятся?
7:32
@sairus_frontend В простых случаях (а их большинство) полагаюсь на вывод

Обычно в таком выводе (хотя это скорее не… twitter.com/i/web/status/1…

7:32

I'm back in black! Давайте еще посмотрим на опции компилятора

Стоит включить --forceConsistentCasingInFileNames: д… twitter.com/i/web/status/1…

7:44

То есть если кто-то с винды напишет import Component from './mYComPoNenT' это соберется у него и упадет на CI (если… twitter.com/i/web/status/1…

7:44

Кейсинг импорта должен быть консистентным по проекту. То есть если один раз написали правильно, то и в остальных ме… twitter.com/i/web/status/1…

7:44
@jsunderhood Это вообще лист с 4 типами! Как-то я решила использовать enum как включи для анимации в angular – пере… twitter.com/i/web/status/1…

Да, вот еще то что ключа 4 тоже может вызвать проблемы потому что это контринтуитивная фигня

@jsunderhood Это вообще лист с 4 типами! Как-то я решила использовать enum как включи для анимации в angular – пере… twitter.com/i/web/status/1…

7:53

module выставляем в ESNext: собирать наверняка будем каким-нибудь вебпаком или роллапом и это позволит использовать… twitter.com/i/web/status/1…

7:59

От компилятора переходим к организации проекта. Сразу советую создать в корне папку typings и указать ее в typeRoot… twitter.com/i/web/status/1…

8:12

И там уже

declare module "some-library" {
// blabla
}

8:12

Также я считаю всевозможные опции типа webpack alias, tsconfig.paths etc. вредными

Почему? Это нестандартная фича… twitter.com/i/web/status/1…

8:19

А ТС вам и говорит, не знаю что за myRoot, он же не знает ничего про вебпак

Хорошо, добавили в tsconfig.paths, ТС… twitter.com/i/web/status/1…

8:19

Вы наверняка спросите, а как тогда быть c

import Something from '../../../../../../this/is/root/then/its/this/fol… twitter.com/i/web/status/1…

8:41

Про использование symbolic links в кодовой базе даже говорить не хочется

Поэтому файловую систему нужно использова… twitter.com/i/web/status/1…

8:41

Кратко, вместо логической группировки

actions/notifications.ts
actions/chat.ts

reducers/notifications.ts
reducers… twitter.com/i/web/status/1…

8:43

В редаксе это называется ducks, детали могут варьироваться, но я думаю общая мысль понятна

freecodecamp.org/news/scaling-y…

8:45

Rule of a thumb: не создавать папку без надобности, в случае необходимости стараться группировать по функционалу

Э… twitter.com/i/web/status/1…

8:50

Пока сделаем паузу, потом продолжим про всякие фп концепты и как мы будет их использовать в нашем проекте

8:53
@jsunderhood @rm_baad @HolyJSconf Не, ну а как ты будешь работать с декораторами без рефлекта? Используют конечно
9:52
@amel_true @rm_baad @HolyJSconf Кажется я неверно понимал опцию

Я думал что думал что некий рефлект (имя свойств н… twitter.com/i/web/status/1…

9:52
@jsunderhood ты вроде шаришь, расскажи плз как без боли (диких хелперов) сделать Conditional optional type
или вр… twitter.com/i/web/status/1…

Это распостраненная ошибка - делать перегрузки через conditional, обычно это заканчивается болью

Перегрузки можно… twitter.com/i/web/status/1…

@jsunderhood ты вроде шаришь, расскажи плз как без боли (диких хелперов) сделать Conditional optional type
или вр… twitter.com/i/web/status/1…

9:59

1 Стандартный встроенный способ
typescriptlang.org/docs/handbook/…

function foo(arg: { a: string })
function foo(arg: { b: st… twitter.com/i/web/status/1…

9:59

2 То же самое можно выразить через юнион инвариантов

type Arg = { a: string } | { b: string } | { a: string, b: st… twitter.com/i/web/status/1…

9:59
@cakeinpanic @jsunderhood В webstorm есть. Можно еще и ренеймить строки в alias'ах, а также заменить такой type ali… twitter.com/i/web/status/1…
10:40
@cakeinpanic @jsunderhood Он есть, но его нужно явно вызывать
11:26

# Пятница 47 твитов

@jsunderhood Не согласен с paths - по другому монорепу не настроить
7:47
@b2whats Ну да, монорепе это необходимое зло как мне кажется. Я больше про неоправданне использование
7:47
@ch_ronik @jsunderhood ну конкретно для "непустого объекта" - Input extends {[key:
never]: any} ? never : Optional<Type>

Сева врывается с хардкорчиком

@ch_ronik @jsunderhood ну конкретно для "непустого объекта" - Input extends {[key:
never]: any} ? never : Optional<Type>

7:58

Вчера вечером забухал (шучу, были дела) поэтому продолжаем с утреца

8:00

Где код писать понятно, как код писать понятно, но какой код писать??

Давайте поглядим на всякие штуки которые в т… twitter.com/i/web/status/1…

8:01

Начнем с инвариантов. Если ко/контра вариантность может показаться сложной для понимания, то в инвариантах сложное… twitter.com/i/web/status/1…

8:11

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

type Data = {
data?: string
loading?: boolean
error?: Error
}

П… twitter.com/i/web/status/1…

8:11
@jsunderhood Ну, вообще, если хочется, то ФС позволяет. Есть несколько способов, и, в частности, `GetFinalPathNameB… twitter.com/i/web/status/1…
8:12
@jsunderhood Идеальный проект остаётся идеальным не так уж долго 🙄

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

@jsunderhood Идеальный проект остаётся идеальным не так уж долго 🙄

8:57

Но сколько состояний в реальности? Вероятно 4

| { loading: false }
| { loading: true }
| { data: string, loading:… twitter.com/i/web/status/1…

9:15

На таком маленьком примере не очень понятно в чем профит, но такой подход зачастую отлично ложиться на разные домен… twitter.com/i/web/status/1…

9:29

Опять же если выражать это через опциональные поля выйдет как-то так

{
username: string
role: 'regular' | 'gol… twitter.com/i/web/status/1…

9:29

Пишем

const renderSubscriptionEnd = (date: Date) => {...}

if (user.role === 'gold')
renderSubscriptionEnd(user.… twitter.com/i/web/status/1…

9:29

Окей, давайте проверим

const renderSubscriptionEnd = (date: Date) => {...}

if (user.role === 'gold' && user.subsc… twitter.com/i/web/status/1…

9:29

Давайте объясним это компилятору!

type BaseUser = {
username: string
}

type RegularUser = BaseUser & {
role:… twitter.com/i/web/status/1…

9:29

И теперь тот же самый код работает!

const renderSubscriptionEnd = (date: Date) => {...}

if (user.role === 'gold')… twitter.com/i/web/status/1…

9:29

Потому что раньше было 4 варианта юзера

{ role: 'regular' }
{ role: 'regular', subscriptionEnd: new Date() }
{ rol… twitter.com/i/web/status/1…

9:32
@jsunderhood +updating
+deprecated
И с ними ошибка играет новыми красками
9:32

И компилятору легче просечь что вы имели ввиду

Этим мы получили тот самый discriminated union о котором я говорил… twitter.com/i/web/status/1…

9:44

А знаете что еще классно на это ложится? Экшены в редаксе!

Так как type это у нас string literal (к тому же с помо… twitter.com/i/web/status/1…

9:44

Также можно делать exhaustive checking. Это следующая фигня, если мы выразим те экшены которые обрабатывает редьюсе… twitter.com/i/web/status/1…

9:48

type LoadAction = { type: 'LOAD' }
type SuccessAction = { type: 'SUCCESS' }

const reducer = (state, action: LoadAc… twitter.com/i/web/status/1…

9:48

Работает это так, что ТС зная что приходят два вот таких экшена (которые он умеет отличать друг-от-друга, hence the… twitter.com/i/web/status/1…

9:51

never обладает следующими свойствами

never is assignable to anything
nothing except never is assignable to never… twitter.com/i/web/status/1…

10:01

Соответсвенно когда мы забудем обработать какой-то экшен то ТС будет ругаться что этот экшн not assignable to never… twitter.com/i/web/status/1…

10:01

case 'ACTION':
return {
...state,
blaba
}

При слиянии потеряли 'return {' и потом вернули '{', а retur… twitter.com/i/web/status/1…

10:01

Теперь о номинальных типах. Номинальная совместимость (по имени) противопоставляется структурной совместимости (по… twitter.com/i/web/status/1…

10:57

А например в C# нет
class A { public field: string }
class B { public field: string }

void Foo(obj: B) {}

Foo(new A()) // Ошибка

10:57

Так вот, о номинальных типах. Во-первых в ТС их нативно нет, приходится костылить Во-вторых, собственно, нафига?

С… twitter.com/i/web/status/1…

10:57

Например id у разных сущностей. Представим что у нас есть компонент который принимает id юзера и грузит его карточк… twitter.com/i/web/status/1…

11:00

На помощь приходят брендированные типы

type UserId = number & { readonly __brand: unique symbol }

declare functio… twitter.com/i/web/status/1…

11:06
@jsunderhood По факту

enum Colors {
Red: 'red',
Blue: 'blue'
}

это сочетание объекта

const Colors = {
Red… twitter.com/i/web/status/1…

11:15
@i_kabirov 1) Тип можно вывести

2) Второй вопрос не понял

Но можно просто написать keyof typeof svg и он автоматом возьмет все свойства svg!

Самое полезное здесь конечно то… twitter.com/i/web/status/1…

11:15
@jsunderhood 1. Я не про ключи, я про union значений
11:15
@i_kabirov Если вам зачем-то нужен юнион значений (зачем кстати) то можно сделать

const colors = {
RED: 'red',… twitter.com/i/web/status/1…

11:15
@i_kabirov Про числа я считаю что енам норм

twitter.com/jsunderhood/st…

Но в целом никто не мешает сделать так
const… twitter.com/i/web/status/1…

2 Для придавания семантики числовым опциям. Этим опять же может грешить бэк и принимать вместо строковых ключей - ч… twitter.com/i/web/status/1…

11:15

Таким же образом можно брендировать и объекты, чтобы защититься от похожего по структуре, но неподходящего объекта… twitter.com/i/web/status/1…

11:17

И напоследок немного хардкора: opaque types

Opaque (непрозрачный) type это такой тип который

1) Номинальный
2) Ум… twitter.com/i/web/status/1…

14:05

Их опять же в ТС нет поэтому будем костылить. Кода там сильно больше поэтому вот плейграунд (он почему-то показывае… twitter.com/i/web/status/1…

14:05

В чем прелесть? Прелесть в том что так мы инкапсулируем внутреннюю структуру нашего игрового поля (как в ООП), но п… twitter.com/i/web/status/1…

14:05

В моем примере внешний пользователь вообще ничего не знает про Game, но естественно можно искапсулировать по частям… twitter.com/i/web/status/1…

14:05

Да, писать довольно муторно и неудобно, но это просто потому что нет нативной поддержки

Во flow это opaque (через… twitter.com/i/web/status/1…

14:06

Вот такие у меня мысли по поводу того как писать на ТС

Следующий тред будет про Reason и немного про другие языки

14:08
@jsunderhood Ухх эти типы! Я вот до сих пор не понимаю в чем отличие interface и type в последних версиях TS 🤯 В од… twitter.com/i/web/status/1…

Точно, забыл, очень популярный вопрос

Стоит использовать type

* & (intersection) можно выразить через extends, а… twitter.com/i/web/status/1…

@jsunderhood Ухх эти типы! Я вот до сих пор не понимаю в чем отличие interface и type в последних версиях TS 🤯 В од… twitter.com/i/web/status/1…

16:22

* У interface корявенький синтаксис для того случая когда интерфейс - функция

interface Foo {
(arg: Arg): Return… twitter.com/i/web/status/1…

16:22
Кстати до 3.6 был интересный хак чтобы обходить такое

Дело в том что по стечению обстоятельств type вычисляется ea… twitter.com/i/web/status/1…

interface нужно использовать когда:

1) Вы пишете библиотеку: ибо interface поддерживает declaration merging, что п… twitter.com/i/web/status/1…

Кстати до 3.6 был интересный хак чтобы обходить такое

Дело в том что по стечению обстоятельств type вычисляется ea… twitter.com/i/web/status/1…

16:25
@jsunderhood Интерфейс выгоден, когда ты создатель либы и хочешь дать возможность людям играться с твоими типами. П… twitter.com/i/web/status/1…

Даже не то что выгоден, по возможности обязателен

Спасибо за бдительность однако

@jsunderhood Интерфейс выгоден, когда ты создатель либы и хочешь дать возможность людям играться с твоими типами. П… twitter.com/i/web/status/1…

16:30

# Суббота 51 твит

Теперь повысим градус типизации и ФП почти до финала: поговорим о моей тайной (на самом деле не очень) любви: Reaso… twitter.com/i/web/status/1…

17:54

Во-первых во флоу есть полноценный вывод типов
В ТС весь вывод работает вниз по АСТ (с уточнениями)

Это означает ч… twitter.com/i/web/status/1…

17:54

И с возвращаемым типом тоже справится (хотя и не всегда)

const foo(a: { field: string }) => a.field

17:54

А вот аргументов функции уже нет, потому что объявление функции должно быть до ее вызова

const foo = (a) => a

foo… twitter.com/i/web/status/1…

17:54

Так вот флоу это разрулит!

Он как-бы решает огромное уравнение где типы это переменные и смотрит сходится все или… twitter.com/i/web/status/1…

17:54

Таким образом, в теории, можно вообще не писать типы!

То есть статические проверки у нас есть, а типы мы не пишем! Isn't that wonderful

17:54
Дико поддержу

Кто-то где-то сказал что у статической типизации ужасный UX

И это правда так, типы обычно не говоря… twitter.com/i/web/status/1…

На практике конечно не все так гладко. Я уже говорил что у типизации плохой UX

twitter.com/jsunderhood/st…

Но использ… twitter.com/i/web/status/1…

Дико поддержу

Кто-то где-то сказал что у статической типизации ужасный UX

И это правда так, типы обычно не говоря… twitter.com/i/web/status/1…

18:15

Может быть два модуля которые встречаются в третьем месте. Ошибка может быть как в середине так и в самом модуле, н… twitter.com/i/web/status/1…

18:15

Все что внутри наоборот типизировать не стоит, ибо это усложняет рефакторинг (явно аннотирование публичного контракта же упрощает)

18:15
@jsunderhood К сожалению, это лишь в теории. Чем больше кода в проекте, тем больше он становится похожим на эту гиф… twitter.com/i/web/status/1…
18:15

Есть еще одна интересная особенность систем типов и систем вывода типов: чем более экпрессивна система типов, тем с… twitter.com/i/web/status/1…

18:18

В итоге трейдоффы на трейдоффах, грустно конечно, но что поделать

Тем не менее вывод типов это крутая штука и не с… twitter.com/i/web/status/1…

18:22

Во флоу есть нативные opaque типы через которые также можно делать номинальные типы

flow.org/en/docs/types/…

18:22

Во флоу также есть более интересные utility types, например $Call
flow.org/en/docs/types/…

Кто-то может возразить ч… twitter.com/i/web/status/1…

18:32

То есть если функция возвращает разное в разных случаях (читай перегрузки) то флоу высчитает соответствующий тип

Т… twitter.com/i/web/status/1…

18:32

Это я все не к тому что ТС плохой и не к холивару, а к тому что стоит всегда интересоваться тем что происходит вне… twitter.com/i/web/status/1…

18:34

Еще немного истории, был такой язык OCaml сделали в 1996 году. Это был (и есть) мультипарадигменный язык из ML семе… twitter.com/i/web/status/1…

18:43

Язык очень хороший и Фейсбук думал как бы с его помощью делать фронтенд круче. Первая попытка видимо была флоу, но… twitter.com/i/web/status/1…

18:48

Потому что им в голову пришла другая идея: а что если писать фронтенд на окамле и компилировать в жс? Идея конечно… twitter.com/i/web/status/1…

18:54

Слишком чужеродный синтаксис, слишком неприятно мапится на JS.

Хорошо, а что если сделать синтаксис гораздо ближе… twitter.com/i/web/status/1…

18:54

That's how Reason was born. Что радует отдельно - остается верным этому по сей день. Прежде чем мы перейдем к самом… twitter.com/i/web/status/1…

19:04

1) Несмотря на то что он general purpose, reason изначально придуман чтобы компилироваться в жс. Для F# есть Fable,… twitter.com/i/web/status/1…

19:08

2) Опять же несмотря на то что он для веба, он имеет практически полную AST совместимость с OCaml. То есть вы может… twitter.com/i/web/status/1…

19:13

А экосистема (в том числе пакетов) будет одна! На самом деле экосистемы две: веб и натив, но про натив будет потом… twitter.com/i/web/status/1…

19:13
@jsunderhood Не уверен, что было именно так. До Reason в недрах Bloomberg был создан Bucklescript для компиляции OC… twitter.com/i/web/status/1…

Это очень важное дополнение, спасибо большое

Тут стоит упомянуть то что OCaml и до bucklescript умел компилиться в… twitter.com/i/web/status/1…

@jsunderhood Не уверен, что было именно так. До Reason в недрах Bloomberg был создан Bucklescript для компиляции OC… twitter.com/i/web/status/1…

19:18

Bucklescript же придумал новый очень тонкий рантайм и stdlib (Belt) который позволил это все реально использовать д… twitter.com/i/web/status/1…

19:18
@jsunderhood На этой неделе просто рекорд добавленных в закладки тредов. Человек аккумулирует кучу знаний в простой… twitter.com/i/web/status/1…

Рад стараться!

@jsunderhood На этой неделе просто рекорд добавленных в закладки тредов. Человек аккумулирует кучу знаний в простой… twitter.com/i/web/status/1…

19:19

3) Язык и экосистема активно развиваются. Я помню как смотрел доклад Patrick Stapfer про reason в 2017, помню как н… twitter.com/i/web/status/1…

19:29

4) Комьюнити небольшое (по сравнению с тем же ТС), но фб действительно в это вкладывается. На дискорде сидят кор ко… twitter.com/i/web/status/1…

19:31
@jsunderhood Блумберьх подарил нам хороший бэкенд, а мордокнига — фронт языка, которого js-ники не боятся. Слава OC… twitter.com/i/web/status/1…
19:32

Это те причины почему я верю в язык и комьюнити

Теперь давайте наконец-то про сам язык!

19:34

Во-первых есть полноценный вывод типов

Про него я уже рассказал выше

19:40

Во-вторых есть компилятор (bucklescript.github.io) который имеет очень тонкий рантайм и стандартную библиотеку (Be… twitter.com/i/web/status/1…

19:45

Я сначала подумал что это лажа. Но со временем понял приемущество такого подхода. Ведь несмотря на то что ризон гор… twitter.com/i/web/status/1…

19:47
@jsunderhood Ну совсем не писать нельзя. Но достаточно описать аргументы функций/классов которые экспортятся.

Спасибо, я забыл упомянуть что флоу как раз использует эту концепцию

@jsunderhood Ну совсем не писать нельзя. Но достаточно описать аргументы функций/классов которые экспортятся.

19:48

В-третьих в нем есть функциональные компоненты, иммутабельные списки (в которые быстро писать в начало), рекорды и… twitter.com/i/web/status/1…

19:55

В-четвертых в нем есть те структуры которые более похожи на жс, мутабельные массивы, Js.Dict для объекта как мапы и… twitter.com/i/web/status/1…

19:58
@jsunderhood 🤦‍♂️Так говорят только хейтеры flow.

А теперь посмотри сюда и скажи насколько flow заброшен.… twitter.com/i/web/status/1…

На самом деле я рад что флоу продолжает развиваться

Но так или иначе фб в какой-то момент потерял доверие комьюнит… twitter.com/i/web/status/1…

@jsunderhood 🤦‍♂️Так говорят только хейтеры flow.

А теперь посмотри сюда и скажи насколько flow заброшен.… twitter.com/i/web/status/1…

20:03

В-пятых в нем удобный interop с js (привет Elm)
reasonml.github.io/docs/en/interop

Что еще прикольней так это то что помимо т… twitter.com/i/web/status/1…

20:08

В-шестых в нем есть first class поддержка React
reasonml.github.io/reason-react/d…

Вот так выглядит функциональный реакт комп… twitter.com/i/web/status/1…

20:11

Получается семантичненько
open Path

let root = create("/")
let myFolder = create("saito/code")
let myPath = root // myFolder

20:24

Тут я использовать еще одну фичу: синтаксис открытия модуля

Вообще все модули находяться в глобальной области види… twitter.com/i/web/status/1…

20:26

Но Path.// выглядит особенно уродливо. К счастью есть scoped open module

Path.(
// мы открыли модуль пока мы в (… twitter.com/i/web/status/1…

20:28

Но опять же, это все документация и насущное, вернемся к практике

Давайте о том что же в ризоне нет/сильно недостает

20:33

1) Нет сормапов. В этом ключе читаемые скомпилированные исходники (а там кстати ES5) становятся особенно полезными.… twitter.com/i/web/status/1…

20:33

2) Нет async/await. Надежды есть, в окамл 4.08 завезли сахар для монад (а промис это почти монада), похожий на comp… twitter.com/i/web/status/1…

20:36

3) Есть некоторые проблемы с динамическими импортами. Во всяком случае были год назад, тогда на ReasonConf чуваки и… twitter.com/i/web/status/1…

20:38

Но в целом только вот эти три крупные проблемы (во всяком случае которые испытал я)!

20:39

Ах, ну да, еще то что любой другой фреймворк (вуй, ангуляр) кроме реакта завести в ризоне будет крайне тяжело

Либы… twitter.com/i/web/status/1…

20:43

Тут я скину несколько ссылок
Доки ризона
reasonml.github.io/docs/en/what-a…

Доки reason-react
reasonml.github.io/reason-react/d…

Доки b… twitter.com/i/web/status/1…

20:44
@jsunderhood насчёт типизации, смотрел Idris?

Сам руками не трогал, но coq и idris это конечно круто

Кому интересно про типы
youtu.be/nFtO6419A5ktwitter.com/i/web/status/1…

@jsunderhood насчёт типизации, смотрел Idris?

21:29

# Воскресенье 36 твитов

Did you ever implement (or try) event listener pattern by youself?

Попросили ретвитнуть, сложно отказать, ответьте на опрос если не сильно лень

Did you ever implement (or try) event listener pattern by youself?

16:50

Сегодня мой последний день здесь, я конечно порядком подустал за неделю, но и все донести тоже не успел

Поэтому по… twitter.com/i/web/status/1…

17:08

Итак, вот у нас ест фронтенд который как-то получает данные от бэкенда

Если мы используем статическую типизацию то… twitter.com/i/web/status/1…

17:15

Если рассмотреть типичную ситуацию с Rest Api и Json то это будет выглядеть как-то так

type User = { id: number }… twitter.com/i/web/status/1…

17:15
@jsunderhood На самом деле разруливает он данный случай не так хорошо как могло быть. Есть 2 ветки систем типов: Hi… twitter.com/i/web/status/1…

Да, согласен, отличное дополнение

@jsunderhood На самом деле разруливает он данный случай не так хорошо как могло быть. Есть 2 ветки систем типов: Hi… twitter.com/i/web/status/1…

17:24

Но здесь на самом деле происходит неявная конвертация из any в User! Потому что на самом деле нет никаких гарантий… twitter.com/i/web/status/1…

17:33

Но зачем мы тогда пишем типы, включаем strict если оно все равно может спокойно упасть в рантайме по совершенно бан… twitter.com/i/web/status/1…

17:33

Есть радикальные способы: смена способа общения на такую, которая гарантирует проверку данных: тот же protobuf скаж… twitter.com/i/web/status/1…

17:33
Для того чтобы доказать используются type refinements (они же type guards)
Выглядеть может примерно так

Можете пои… twitter.com/i/web/status/1…

Но что же делать если на GraphQL и даже Swagger бэкендеры не соглашаются (например это внешний сервис), а проверять… twitter.com/i/web/status/1…

Для того чтобы доказать используются type refinements (они же type guards)
Выглядеть может примерно так

Можете пои… twitter.com/i/web/status/1…

17:41

Наивным подходом будет просто писать валидаторы руками. Взяли какой-нибудь github.com/ianstormtaylor… и написали

17:41

import { struct } from 'superstruct'

type User = { id: number }

const User = struct({
id: 'number',
})

const g… twitter.com/i/web/status/1…

17:41

Проблема здесь я думаю налицо: как держать тип и валидатор в синхронизации? Любое изменение как валидатора, так и т… twitter.com/i/web/status/1…

17:44

Чтобы удобно синхронизировать их, нужно иметь single source of truth. Их потенциально тут два: либо тип, либо валид… twitter.com/i/web/status/1…

17:47

Короче, можно написать валидатор и из него уже вывести тип, комбинируя валидаторы! Самый известный представитель эт… twitter.com/i/web/status/1…

17:47

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

1) Использование вывода там на полную ка… twitter.com/i/web/status/1…

17:49

2) Развесистая фигня, требующая времени чтобы понять что тут к чему

3) Непростая интеграция в существующий проект

17:50

Альтернативой будет взять тип и по нему сделать валидацию. Это вполне распространенный подход в ООП языках которые… twitter.com/i/web/status/1…

18:10

Точнее типы конечно есть, да не те. Мы то хотим сделать валидацию по type User = { id: number }, но при компиляции… twitter.com/i/web/status/1…

18:10
@jsunderhood У меня всего один вопрос. Как этим пользоваться если я не упоротый функциональщик? Я честно пытался, о… twitter.com/i/web/status/1…

Да, есть такое, io-ts апи очень фпшное и завязано на Either из fp-ts

Я бы предложил не мучится и написать хелпер к… twitter.com/i/web/status/1…

@jsunderhood У меня всего один вопрос. Как этим пользоваться если я не упоротый функциональщик? Я честно пытался, о… twitter.com/i/web/status/1…

18:19

Что-то типа

import * as t from 'io-ts'
import { isRight, Either } from 'fp-ts/lib/Either'

const User = t.type({… twitter.com/i/web/status/1…

18:19

// бросит ошибку в случае ошибки валидации
const user = eitherToThrow(
User.decode(
JSON.parse('{"userId":1,"… twitter.com/i/web/status/1…

18:19

Вариант номер раз: отправить информацию о типах в рантайм. Это как раз и есть reflect-metadata о которых мы говорил… twitter.com/i/web/status/1…

18:26

1) Декоратор должен быть повешен на поле реального объекта или класса, то есть вы не можете написать

type User = {… twitter.com/i/web/status/1…

18:26

Получается вот это pic.twitter.com/qziBDHvo3p

18:33
@jsunderhood Можно использовать github.com/aeirola/io-ts-…
18:33

Я даже написал рабочую либу!

github.com/ts-type-makeup…

Вообще с помощью такого подхода можно делать еще много всяки… twitter.com/i/web/status/1…

18:36

Но конечно с такой силой приходят и недостатки. Никакие из них не являются нерешаемыми (разве что один), но я начал… twitter.com/i/web/status/1…

18:43

1) Пока это работает только через typescript transformer
Я написал доки как интегрировать это с ts-loader и ts-node… twitter.com/i/web/status/1…

18:43

2) Пока нет поддержки кастомных валидаторов

А это crucial thing, чтобы можно было написать валидатор для UUID, ISO… twitter.com/i/web/status/1…

18:49

Планирую поддержать это через user type guards и Branded types
import _isUuid from 'is-uuid'

type Uuid = string &… twitter.com/i/web/status/1…

18:49

3) Проблема связанная конкретно с тем что мы фактически имплементируем c++ templates
github.com/ts-type-makeup…

Для к… twitter.com/i/web/status/1…

18:54

Но если кто-то сделает

const myValidate = <T>(jsonStr: string) =>
validate<T>(JSON.parse(jsonStr));

То нам прид… twitter.com/i/web/status/1…

18:59

Соответственно я сначала должен найти вызовы моей функции. Если я нахожусь в теле другой функции дженерик которой п… twitter.com/i/web/status/1…

18:59

Я призываю компиляторщиков которые наставят меня на путь истинный и подскажут что курить и как с этим бороться

19:00

Вот такие пироги! Ставьте звездочки, а также обратите внимание что либа имеет полный набор честных e2e (если можно… twitter.com/i/web/status/1…

19:02

И на этой позитивной ноте я с вами прощаюсь (в реплаях может еще поотвечаю)! С вами был Майк Башуров aka… twitter.com/i/web/status/1…

19:14

github.com

www.typescriptlang.org

other