Архив недели @n_gafarov
Понедельник
Всем привет. Меня зовут Гафаров Назим @n_gafarov
Вы могли видеть меня в качестве докладчика на Яндексовых мероприятиях, HolyJS и других конференциях. Изредка пишу статьи на Хабре, где пытаюсь несмешно шутить с помощью непонятных отсылок.
Короткий рассказ о себе.
В 2015 году я работал в стартапе, который делал "убийцу" Amazon Kindle для школьников. Стартап стал частью издательства "Дрофа", а я в 2017 году стал частью Яндекса.
В Яндекс.Маркете я начал работу над "убийцей" Amazon - маркетплейсом "Беру", а точнее, над админкой для партнеров.
Через полтора года принял от Mail.ru Cloud Solutions предложение делать "убийцу" Amazon Web Services.
Слова благодарности друзьям за поддержку


На этой неделе я планирую давать короткие полезные советы, которые можно быстро применить в своей работе. Поїхали.
Тред (Назим Гафаров)
Как и при старте нового проекта, начнем с особенностей package.json
⬇️ Начнем
В блоке скриптов package.json не должно быть никаких платформо-зависимых команд. Например, оператор & в Windows Cmd.exe ведет себя не так, как в bash. Для параллельного и последовательного запуска команд лучше использовать npmjs.com/package/npm-ru…
Кроме того, npm-run-all позволяет одной командой запускать несколько сценариев. Вместо:
npm run build:css && npm run build:js && npm run build:html
можем написать:
npm-run-all build:*
"test": "npm-run-all --parallel test:"
"test:lint": "eslint '**/.{ts,tsx}'"
"test:types": "tsc"
"test:unit": "react-scripts test --watchAll=false"
Просто и чётко, как png.
Аудит безопасности пакетов должен стать частью CI/CD. Органично впишем в наш список команд:
"test:audit": "npm audit --audit-level=high"
docs.npmjs.com/cli/v6/command…
Также имеет смысл добавить package.json свойство:
"private": true
Чтобы случайный npm publish не выкатил ваш код в публичный npm. Если вы думаете, что с вами такого никогда не произойдет, то у вас "optimism bias" (sciencedirect.com/science/articl…).
В старых проектах еще бывает полезно время от времени проверять package.json на неиспользуемые пакеты. В этом помогает depcheck и npm-check.
У них, конечно, бывают проблемы с ложноположительными результатами, обычно из-за webpack resolve.alias. Но в целом, свою задачу решают.
Тред (Назим Гафаров)
package-lock.json
⬇️
Во-первых, имеет смысл приучить всех в команде пользоваться командой "npm ci" при установке зависимостей, а не "npm install". Это полезно не только в CI/CD, но и при локальной разработке, т.к. обычно у разработчиков разные версии npm, и пакеты могут резолвиться по-разному.
В итоге npm install нужно использовать только при добавлении новых пакетов в проект.
Если вам надоели пул-реки с +2к изменений, то можно написать тест, который будет падать, если в PR есть изменения в package-lock файле и при этом нет изменений в package.json
Чтобы npm install у всех разработчиков резолвил пакеты одинаково, нужно договориться, чтобы все сидели на одной версии Node и npm (обычно это LTS). Добавьте эту версию в поле engines:
docs.npmjs.com/cli/v6/configu…
А так как лучше доверять машинам, а не людям, то есть смысл декларативно описать окружение с помощью github.com/infinitered/so… и проверять его при каждом коммите (husky + lint-staged).
Тред (Назим Гафаров)
В package.json всегда имеет смысл указывать конкретные версии, особенно в dependencies секции. Указывая примерные ~version или совместимые версии ^version, вы как бы говорите себе:
«Все JavaScript-разработчики – это разумные люди, которые строго следуют semver».
И, пожалуйста, никогда не используйте yarn в продакшене.
Yarn - это песочница, в которой тестируются самые безумные идеи. Когда эти идеи стабилизируются, они плавно перетекают в npm. На сегодняшний день единственное преимущество yarn перед npm - это логотип.
Вторник
Yarn крутой, кто ж спорит. Но это не стандарт.
Возьмем например выборочное разрешение зависимостей: classic.yarnpkg.com/en/docs/select…
Отличная функция, но только npm ничего не знает о ваших resolutions в package.json
Во-первых, непонятно как resolutions работает для вложенных зависимостей? Никак: github.com/yarnpkg/yarn/i…
Во-вторых, если вам по какой-то причине нужно будет отказаться от yarn, что вы будете делать?
Пока нормальные ребята думают над import-maps, чтобы механизм резовалва был единый для всех платформ: неважно браузер это, node.js или даже deno (там вообще нет npm).
Как ваши resolutions будут работать в import-maps? Никак: github.com/WICG/import-ma…
Я достаточно старый, чтобы помнить времена, когда вокруг Io.js был такой же хайп, как вокруг yarn сейчас.
Io.js был производительнее и затаскивал новые фичи намного быстрее Node.js
Но используя yarn сегодня вы подписываетесь на то, чтобы быть вечным бета-тестером. В этом нет ничего плохого, но старые люди скорее предпочтут подождать когда yarn вольется в npm и станет там чем-то типа Nightly-версии.
Тред (Назим Гафаров)
Новый день - новая тема. Сегодня обсудим вопросы взаимодействия с бэкендом.
Добрые слова поддержки от друзей на сегодня.


Начнем с BFF.
⬇️
BFF - это адаптер к внешним API, который агрегирует запросы из разных источников и отдает на фронт в удобном для фронта виде.
В Яндексе BFF используется повсеместно. Подробнее в статье от @amel_true - habr.com/ru/company/yan…
BFF - это отличное решение, но только если у вас очень сильная команда инфры. Деплоить, мониторить, балансировать, логировать - все это не так просто, как кажется. Если у вас нет выделенной команды инфраструктуры (или сильных DevOps), не стоит в это ввязываться.
Соло фронтэнд-команда может затащить BFF только в публичное облако. Взять какой-нибудь Serverless Framework и задеплоить в AWS. Будет дорого, но без облака такой же производительности, надежности и масштабируемости добиться почти невозможно.
Однако даже в этом случае вам, скорее всего, нужен будет Cloud DevOps.
Из РФ-провайдеров поддержку Serverless.com я знаю только от Yandex Cloud Functions (github.com/yandex-cloud/s…). Большой минус для остальных провайдеров.
И последнее про serverless. В 2020 году хорошо выстрелил workers.cloudflare.com
За 5$ вы получаете 10 млн. запросов, 1 GB key-value storage и все это автоматически доступно на всех Cloudflare локациях, прямо как CDN. Только не забывайте, что многие подсети все еще в бане РНК.
В итоге, если у вас нет выделенной инфра-команды или вы не чувствуете в себе силы заехать на serverless, разумнее всего не начинать BFF. Я видел кучу примеров, когда команда из двух фронтов начинает играться в бэкендеров. Получается как на картинке:

Отсутствие серверного приложения под фронтом дает кучу преимуществ. Например, mcs.mail.ru - это "голая" статика. Ее можно задеплоить в любой CDN или даже просто в S3.
Стенд на каждую git-ветку, никаких пятисоток, здоровый сон, крепкий аппетит.
Тред (Назим Гафаров)
Идем дальше. Расскажу, что делать, если физрук оставлял вас после уроков и не давал пользоваться GraphQL.
⬇️
GraphQL крут тем, что из коробки дает тебе документацию, валидацию запросов/ответов и TS-типы. Об этом подробно рассказала @pgurtovaya на прошлой неделе.
Но проблема в том, что бэкендеров, которые только вчера отказались от SOAP или RPC в пользу JSON REST API, довольно трудно заставить заехать на GraphQL.
Поэтому расскажу, как получить developer experience хотя бы приближенный к GraphQL.
Первая мысль, которая в такой ситуации приходит в голову, - а давайте сами поднимем GraphQL-сервер и напишем резолверы к существующему REST API.
Об это, например, рассказывал @nodkz на HolyJS: youtube.com/watch?v=CA_ZVf…
Но лично я в таких случаях практикую другой подход. Первым делом нужно попросить от бэкендеров машиночитаемую документацию хоть в каком-нибудь виде. RAML, Postman - не важно. Обычно они соглашаются на Swagger.
Если бэкендеры сопротивляются, то мы сами начинаем писать Swagger внутри фронтовой команды. То есть буквально вручную пишем yaml-схему на методы, которые дергаем и описываем ответы, которые ожидаем.
Из этой схемы дальше мы генерируем TypeScript-типы. Я пробовал разные библиотеки, но остановился на github.com/drwpow/openapi…
Если у тебя клиент на TS, то тебе все равно пришлось бы писать типы вручную. Вместо этого легче написать Swagger-схему и сгенерировать типы.
Но что гораздо круче – это то, что, помимо типов, можно сгенерировать и полноценный клиент с помощью github.com/OpenAPITools/o…
Т.е. не нужно вручную создавать сервисный слой для работы с API, писать реквесты, типизировать вход-выход и т.д.
Качество генераторов (openapi-generator.tech/docs/generators) очень разное. Возьмем, например, typescript-fetch и попробуем сгенерировать клиент для Swagger-схемы с полиморфным ответом oneOf. Что-то типа такого:

Не знаю как оно работает для Swagger v2, но на третьей версии я получаю нормальный тип:
loginMethod(): Promise<LoginSuccess | LoginFail>;
Но вместе с типом генератор решает сходить регуляркой по всему файлу и поставить эту палочку везде, даже в импортах:

Ну а что вы хотели? Это вам не GraphQL.
Подобная проблема описана в ишьюсе github.com/OpenAPITools/o…. Я так понимаю, его просто закрыли год назад.
С typescript-axios (openapi-generator.tech/docs/generator…) таких проблем нет. Поэтому внимательно выбирайте генератор.
Тред (Назим Гафаров)
В итоге из Swagger-схемы вы получаете красивую документацию, типизированный сервисный слой для запросов к API и опциональную рантайм валидацию ответов бэкенда.
Зачем вам GraphQL? Тем более что нормально поддержать GraphQL способны три с половиной бэкендера на планете.
GraphQL отлично зайдет если вы начинаете проект с нуля. В этом случае вы просто берете hasura.io и увольняете всех бэкендеров. Во всех остальных случаях используйте Swagger.
Среда
Прекрасный день, чтобы покинуть свой дворец и окунуться в пучину JavaScript-разработки.
Сегодня обсудим управление состоянием. Если вы думали, что в предыдущие дни были неаргументированные набросы, то вы ошибались.
Чтобы вы правильно понимали ситуацию, я планировал твитнуть "Сегодня расскажу про преимущества редакса" и целый день потом ничего не писать.
Традиционные слова поддержки. На этот раз от благодарных подписчиков.


Если серьезно, то преимущество редакса это иммутабельность. K.O.
Но вы платите огромную цену ради нее - бойлерплейтом, производительностью и скоростью разработки. Поэтому возникает вопрос - действительно ли вам настолько сильно нужна иммутабельность?
⬇️
В какой ситуации вообще вам может понадобиться иммутабельность на фронте? Мне в голову приходит какой-нибудь текстовый редактор, чтобы легко можно было реализовать undo/redo.
Но в реальном мире вам для текстового редактора скорее всего понадобится режим совместного редактирования и там уже нужно реализовывать совсем другие паттерны, а не примитивный Memento.
Говоря о преимуществах иммутабельности, часто упоминают простоту логирования и возможность "поднять" приложение из снапшота состояния. Но почему для логирования вы вдруг решили брать старое состояние, сравнивать его с новым, а разницу выводить?
Почему нельзя просто повесить new Proxy() и логировать вообще все что угодно, хоть каждое обращение к объекту?
Ах да, в IE11 ведь нету Proxy. Ну что ж, печально работать на проекте, который поддерживает браузер, от поддержки которого год назад отказался сам Microsoft.
По правде говоря, редакс-фанбоям не нужна иммутабельность сама по себе. Их просто привлекает "ореол крутости" ФП - чистые функции и все такое. В таких случаях я объясняю фанбоям, что методы MobX хоть и не являются чистыми, но они идемпотентные.
Конечно большинство фанбоев ничего не слышали про идемпотентность, но "крутость" этого слова заставляет их успокоиться и хотя бы посмотреть в сторону MobX.
Тред (Назим Гафаров)
Второе преимущество Redux - его дикая популярность. Расскажу, что делать, если в детстве трудовик оставался с вами наедине, сажал к себе на колени и заставлял писать на Redux.
⬇️
Благодаря повальной чипизации населения общий интеллектуальный уровень людей растет. Поэтому каждый год удовлетворенность Редаксом падает, с 93% в 2016 году до 67% в 2020: 2020.stateofjs.com/ru-RU/technolo…
Так что имеет смысл хотя бы познакомиться с альтернативами.
Если же в 2021 году вы начинаете новый проект с Redux, то имеет смысл задуматься о своем предназначении в жизни. Разве для этого вы родились? Чтобы писать бесконечный бойлерплейт?
Возьмите хотя бы redux-toolkit.js.org и забудьте про трудовика как про страшный сон.
Ну а если вы начали новый проект с Redux-Saga, то имеет смысл сменить профессию.
Тред (Назим Гафаров)
Так какой способ работы со слоем данных мне выбрать? Если посмотреть на stateofjs, то у вас всего два варианта:
GraphQL, Apollo, Relay
MobX
С первым вариантом мы вчера определились, что GraphQL-бэкенд вам никто не даст. Поэтому остается один единственный правильный вариант - MobX.
О плюсах и минусах MobX подробно написано в статье habr.com/ru/company/mai…
Четверг
Отличная вчера была аквадискотека, но во всем важна умеренность. Сегодня не будет никакой провокации. Давайте вместе определим темы:
🤔
28.6%
Идеальное собеседование🤔
40.9%
Тестирование фронта🤔
30.5%
Похудение на 15 кг за годТрадиционный обзор сентимента. Наблюдаем сильную поляризацию в обществе.


Победило тестирование. Начнем с обсуждения того, из-за чего чаще всего возникают баги на фронте.
⬇️
99% багов возникают на стыке систем. Условно говоря , на фронте все ок, на бэке все ок, а баги возникают в процессе их взаимодействия. Бэкенд поменял формат ответа и забыл вас об этом предупредить - и все сломалось. Поэтому в первую очередь решите вопросики с бэкендом.
Научите бэкендеров версионировать API и расширять ручки без ломающих изменений. Естественно, доверять на слово нельзя. Должны быть автоматические проверки всех ответов бэкенда на соответствие схеме. В GraphQL это работает из коробки.
Если же у вас Swagger, то можно взять любой JSON-валидатор, т.к. формат ответа Swagger это обычная JSON Schema и вы можете взять условный github.com/ajv-validator/… для валидации всех ответов. Чтобы не нагружать клиент, лучше это делать внутри BFF или на стейдже.
Тред (Назим Гафаров)
С бэкендом определились. Идем дальше по пирамиде тестирования.
⬇️
В основе пирамиды на мой взгляд должны стоять не Unit-тесты, а строгая типизация и строгие линтеры. Помимо стандартных ESlint-плагинов, типа react, react-hooks, jsx-a11y, node, promise, import и т.д., обратите внимание на:
github.com/SonarSource/es… и github.com/sindresorhus/e…
Готовые конфиги (типа eslint-config-airbnb) мне не нравятся тем, что они смешивают стилистические и логические правила. Для стилистических обычно хватает prettier.io, а логические придется вручную собирать среди кучи плагинов, о которых я говорил выше.
В погоне за высоким покрытием, многие фронты упарываются по jestjs.io/docs/ru/snapsh… (не путать с тестированием скриншотами!)
Но я не понимаю что именно тестирует snapshot. Какая мне разница в какую структуру отрендерился React? Какие гарантии нам дает эта структура?
В теории звучит классно: кидаем в пропсы {isLoading: true} и в снапшоте мы увидим что срендерился какой-нибудь <Spin />. А если кто-то сломает наш компонент, то мы визуально (!) увидим, что снапшот поменялся и теперь там нет спиннера.
Секрет в том, что никто никогда не смотрит что там в снапшоте. Потому что они огромные и постоянно меняются.
Но если хотите продать бизнесу идею, что у вас покрытие тестами 146%, то можно использовать.
Нормальный тест в этом случае должен быть примерно таким: рендерим компонент с { isLoading: true }, а в теле компонента просто ищем <Spin /> с помощью enzymejs.github.io/enzyme/
Нашли - хорошо, нет - нет.
Тред (Назим Гафаров)
Что взять для UI/E2e-тестов?
⬇️
Используя Selenium-библиотеки вы получаете кучу очень хрупких абстракций. Возьмем, например, yandex.ru/dev/hermione/:
Hermione => WebdriverIO => Selenium => Java-интерфейс => драйвер под конкретный браузер.
На каждом из уровней вас ждут проблемы, прям как в фильме "Начало".
Поэтому лучше взять решения, которые базируются на родных API браузеров, например github.com/puppeteer/pupp… или github.com/microsoft/play…
Можно, конечно, писать тесты напрямую в Puppeteer, но вам точно понадобится удобная работа с локаторами, Page Objects и т.д. Поэтому обычно к Puppeteer добавляют среду для тестирования; и лично мой фаворит это codecept.io от @davert
Крутость CodeceptJS в том, что вы можете взять любой раннер, не важно WebDriver или TestCafe, Puppeteer или Playwright. Получается что-то типа DSL, который запустится где угодно. Но только это не DSL, а нормальный JavaScript-код.
Если Puppeteer завтра умрет, как умер WebDriver, то вам не нужно будет переписывать свои тесты.
Окей, а может лучше взять полноценный DSL типа cucumber.io/docs/gherkin/r…? Как раз сможем посадить менеджеров писать E2e-тесты.
Звучит заманчиво, но я никогда не видел чтобы менеджеры или аналитики писали E2e-тесты. А для программистов, Gherkin это лишний слой абстракции, который рано или поздно "протечет" (как и любая другая абстракция).
Подробнее в статье habr.com/ru/post/275013/
Тред (Назим Гафаров)
В итоге идеальное тестирование это:
- TypeScript strict: true
- Prettier + ESLint с кучей плагинов типа SonarJS
- Unit-тесты на логику и утилиты (которая в папке utils, helpers, etc)
- Enzyme-тесты на переиспользуемые компоненты (которые в Storybook)
- E2e-тесты с CodeceptJS
Пятница
В продолжение вчерашней темы про тестирование. Есть вариант почти полностью отказаться от unit- и E2e-тестов, чтобы выпускать релизы быстрее. Для этого нужно всего лишь...
⬇️
Обмазаться кучей технических и бизнесовых метрик
Мониторить ошибки (Sentry и т.п.)
Практиковать Blue-green deployment
Использовать Feature flags с сегментацией аудитории (условно говоря, у вас должна быть возможно открыть фичу для 1% юзеров)
Если все это использовать на максимум, то можно отказаться от кучи тестов и релизиться хоть по 20 раз в день. О любых проблемах вам сообщат метрики и мониторинг.
Новая тема - идеальное собеседование.
В Яндексе я был собеседующим программистом, т.е. проводил интервью и ставил оценки - на какой грейд, на мой взгляд, подходит кандидат. Но я не принимал решение о найме, т.к. собеседование состояло из серии встреч (yandex.ru/jobs/ya-interv…).
⬇️
В Мейле я уже сам нанимал людей в свою команду и принимал решение самостоятельно (вместе с руком группы). Обычно я начинаю со скрининга по базовым JS-вопросам, например typeof []. Дальше можно углубиться - как именно определить массив? Какие минусы у instanceof?
Я не вижу смысла спрашивать WTF-вопросы, типа typeof null или [] * {} - 0 + "", т.к. практического смысла от них нет. Не могу представить, в какой ситуации вам нужно умножать массив на объект. Но знать "4" + 2 было бы неплохо, т.к. даже TS вас от этого не спасет.
В качестве троллинга, чтобы разрядить обстановку, можно спросить typeof(typeof)
Именно в таком написании. Но мне потом всегда становится стыдно за такое поведение 😳
Желательно, чтобы человек знал еще какой-нибудь язык, помимо JS. TypeScript подходит, т.к. считаю его отдельным языком. Обычно проверяется это вопросами на общий кругозор, например, что такое кортеж, множественное наследование и т.п.
Тред (Назим Гафаров)
Конечно от теоретических вопросов на собеседованиях не очень много пользы. Ведь продуктом жизнедеятельности программиста является код. Поэтому кажется разумным оценивать умение писать код. Покажу пример плохой и хорошей задачи на написание кода.
⬇️
Пример плохой задачи - leetcode.com/problems/powx-…
Это плохая задача, т.к. она проверяет знание en.wikipedia.org/wiki/Exponenti…, а не умение писать код. Если бы проверялось умение писать код, то я бы написал:
const str = new Array(n).fill(x).join('*')
return eval(str)
🐸
Пример хорошей задачи: напишите функцию, которая на вход принимает массив типа:
[ {name: "a", value: 1}, {name: "b", value: 2} ]
а на выходе возвращает объект:
{ a: 1, b: 2 }
Казалось бы примитивная задача, но как и FizzBuzz, она круто выявляет пассажиров.
Что может быть проще? Любым перебором прошлись по массиву и заполнили объект. Проблемы начинаются как раз с перебора. Никто почему-то не хочет использовать reduce или forEach или хотя бы for of. Начинают писать обычный for, путаются в индексах и ничего не работает.
Дальше начинаются проблемы со скобочной записью в property accessors. Если бы мне платили по 1$ каждый раз, когда я вижу такой код, то я был бы долларовым миллионером:

А как правильно? Можно было бы просто взять reduce, но если тебе сегодня ко второму уроку, то вот моё решение:
const mapped = arr.map(({ name, value }) => [name, value])
return Object.fromEntries(mapped)
Красиво? Рука сама тянется к солнцу ☀️
Тред (Назим Гафаров)
Ночной JS-TS-Flow срач?
🤔
43.8%
Да🤔
9.8%
Нет🤔
17.0%
Я в доту🤔
29.4%
Мне завтра еще гулятьЧтобы понять насколько Flow превосходит TS достаточно взглянуть на этот код:
type User = string | undefined
const user: User = undefined
const welcome =
Hello, ${user}
В какой ситуации мне может понадобится «Hello, undefined»? При этом Flow мне скажет Cannot coerce user
На этом преимущества Flow заканчиваются. Раньше многие выбирали Flow, т.к. у него была лучше поддержка Реакта. У TS с этим всё было настолько плохо, что я даже топил за связку JSDoc + d.ts youtube.com/watch?v=6WfUDH…
i recently discovered the JSDoc comment form of TypeScript (typescriptlang.org/docs/handbook/…) and it is a goddamn revelation. i'm making last-minute refactors to election code so much more confidently than I otherwise could, but I'm not imposing TS on my coworkers
Подробнее про это см. typescriptlang.org/docs/handbook/…
Даже сегодня такой подход находит сторонников среди лидеров мнений - twitter.com/rich_harris/st…
Если вы пишите на Vue 2, то скорее всего у вас нет другого выбора, кроме JSDoc + ts-check связки.
Но потом Microsoft напряглись и бросили все силы на поддержку React. И у них отлично получилось.
В итоге, выбирать Flow было плохой идеей еще в 2017 году, а сегодня за такое можно вообще в дурку попасть.
Так в чем же проблема заехать полностью на TS и забыть про JS?
Проблема в «Embrace, Extend, and Extinguish».
«Поддержать, надстроить и уничтожить» — фраза, которая, как было установлено Министерством юстиции США, использовалась в корпорации Microsoft ...
... чтобы описать их стратегию внедрения в отрасли программного обеспечения, использующего широко распространённые стандарты, путём расширения этих стандартов и дальнейшего использования этих отличий для получения преимущества над конкурентами.
en.wikipedia.org/wiki/Embrace,_…
Заиграл ли новыми красками TypeScript-слоган «TS это всего лишь надстройка над JS»?
Поддержать, надстроить и уничтожить.
Я понимаю, что это звучит как «покайтесь, ибо грядет», но если оставить Microsoft без конкуренции, то JS-сообществу может быть нанесен сильный урон.
Поэтому, разумно будет поддержать Flow и др. инициативы, типа hegel.js.org, чтобы оказывать постоянное давление на TS
Тред (Назим Гафаров)
Поехали дальше. Как вы думаете, какой тип прописан в TS для аргумента val в Number.isFinite(val)?
Прежде чем ответить, посмотрите спеку метода: tc39.es/ecma262/#sec-n…
- если val равен NaN, +-Infinity или не Number, то верни false
- в остальных случаях верни true
⬇️
Разумно было бы предположить, что сигнатура будет такой:
isFinite(val: unknown): boolean
Но TS считает, что правильнее типизировать так:
isFinite(val: number): boolean
Ну знаешь, передай мне намбер, а я скажу тебе намбер это или не намбер.

Тут можно возразить, типа "передай намбер, чтобы узнать инфинити это или нет". Но у нас нет метода isInteger, а typeof NaN сломан. Поэтому у меня нет другого способа узнать число или нет, кроме isFinite.
У TS была другая мотивация на самом деле github.com/Microsoft/Type…
Это для твой безопасности, сынок. Чтобы ты вместо isFinite(getNumber()) случайно не написал isFinite(getNumber)
В TS 3.8 починили конечно github.com/microsoft/Type… но осадок остался.
Следующий пример чуть сложнее:
const robots = ["R2-D2", "BB-8"]
const isRobot = robots.includes(790)
TS запрещает такое писать, т.к. тип выводится из массива Array<T>.includes. Поэтому я могу передать в includes только строку.
⬇️
Моя логика такая: у меня в справочнике есть список фруктов и я хочу узнать, является ли арбуз фруктом или нет. Я ожиданию простой ответ - да или нет?
includes(val: any): boolean
Но TS говорит мне, что я не могу задавать такой вопрос. Где массив создавали туда и обращайтесь.
Ясно понятно.

Тред (Назим Гафаров)
А как там у нормальных пацанов? В C# нет includes, но есть indexOf:
string[] robots = { "R2-D2", "BB-8" };
int lexx = 790;
int pos = Array.IndexOf(robots, lexx);
C# не ругается, спокойно возвращает -1.
docs.microsoft.com/ru-ru/dotnet/a…
Если же вы посмотрите на includes как на Boolean(Array.find()), то все встанет на свои места.
Но я все равно не согласен с таким поведением. Рано или поздно TS это исправит, как исправили isFinite. Запомните этот твит.

Тред (Назим Гафаров)
Суббота
Идея для исследования. Обучить нейронку, которая по твоим взрослым фоткам определяет - ты это на детской фотографиям или нет.
Может уже есть такое? Или хотя бы датасет.

Сложно придумать какую-нибудь тему на сегодня, помимо политики. По политике в РФ каждый может сделать собственные выводы, поэтому давайте лучше расскажу о том, как и когда Китай загрузит детское порно на ваш компьютер.
⬇️
Многие не знают, что большая часть разработчиков Zoom находятся в Китае и поэтому они открыты для давления китайских властей (citizenlab.ca/2020/04/move-f…). Руководитель Zoom – американец китайского происхождения Eric Yuan.
В 2020 году выяснилось, что сотрудник Zoom сливал китайскому правительству данные пользователей, которые критиковали власть или просто обсуждали события на площади Тяньаньмэнь.
ru.wikipedia.org/wiki/События_н…
Кроме простого отключения таких конференций, сотрудник Zoom создавал поддельные учетные записи на имена полит. диссидентов КНР, чтобы сфабриковать доказательства того, что они подстрекают к насилию и распространяют детскую порнографию.
justice.gov/opa/pr/china-b…
То есть он буквально подделывал скриншоты, на которых неугодные властям люди стоят на фоне флагов запрещенных ближневосточных организаций и транслируют детское порно.
justice.gov/opa/press-rele…
Мораль тут простая:
- не пользуйтесь китайским софтом, в том числе Zoom
- не пользуйтесь китайским железом. Понятно, что так или иначе всё собирается в КНР, но если и R+D китайский (как у Huawei), то бегите, глупцы
- не сливайте свои персональные данные в сервисы, типа TikTok
Надо быть очень отважным, чтобы отправить компартии скан своего паспорта при регистрации в Huawei AppGallery
- не инвестируйте в китайские компании. Не потому что у них рисованная отчетность (quote.rbc.ru/news/article/5…), а потому что риски слишком высокие kommersant.ru/doc/4635638
Тред (Назим Гафаров)
Воскресенье
Неделя подходит к концу. Надеюсь вам понравилось.
Если да, то подписывайтесь на меня тут @n_gafarov или пишите на t.me/ngafarov
