Назим Гафаров

Назим Гафаров

Темы
Неделя
Jan 18, 2021 → Jan 24, 2021

Архив недели @n_gafarov

Понедельник


Всем привет. Меня зовут Гафаров Назим @n_gafarov Вы могли видеть меня в качестве докладчика на Яндексовых мероприятиях, HolyJS и других конференциях. Изредка пишу статьи на Хабре, где пытаюсь несмешно шутить с помощью непонятных отсылок.

Короткий рассказ о себе. В 2015 году я работал в стартапе, который делал "убийцу" Amazon Kindle для школьников. Стартап стал частью издательства "Дрофа", а я в 2017 году стал частью Яндекса.

В Яндекс.Маркете я начал работу над "убийцей" Amazon - маркетплейсом "Беру", а точнее, над админкой для партнеров. Через полтора года принял от Mail.ru Cloud Solutions предложение делать "убийцу" Amazon Web Services.

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

На этой неделе я планирую давать короткие полезные советы, которые можно быстро применить в своей работе. Поїхали.

🔥Тред (Назим Гафаров)
Как и при старте нового проекта, начнем с особенностей 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-версии.

🔥Тред (Назим Гафаров)
Новый день - новая тема. Сегодня обсудим вопросы взаимодействия с бэкендом.

Добрые слова поддержки от друзей на сегодня.
notion image
notion image

Начнем с 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. Я видел кучу примеров, когда команда из двух фронтов начинает играться в бэкендеров. Получается как на картинке:
notion image

Отсутствие серверного приложения под фронтом дает кучу преимуществ. Например, 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. Что-то типа такого:
notion image

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

Ну а что вы хотели? Это вам не GraphQL. Подобная проблема описана в ишьюсе github.com/OpenAPITools/o…. Я так понимаю, его просто закрыли год назад. С typescript-axios (openapi-generator.tech/docs/generator…) таких проблем нет. Поэтому внимательно выбирайте генератор.

🔥Тред (Назим Гафаров)
В итоге из Swagger-схемы вы получаете красивую документацию, типизированный сервисный слой для запросов к API и опциональную рантайм валидацию ответов бэкенда. Зачем вам GraphQL? Тем более что нормально поддержать GraphQL способны три с половиной бэкендера на планете.

GraphQL отлично зайдет если вы начинаете проект с нуля. В этом случае вы просто берете hasura.io и увольняете всех бэкендеров. Во всех остальных случаях используйте Swagger.

Среда


Прекрасный день, чтобы покинуть свой дворец и окунуться в пучину JavaScript-разработки.

Сегодня обсудим управление состоянием. Если вы думали, что в предыдущие дни были неаргументированные набросы, то вы ошибались. Чтобы вы правильно понимали ситуацию, я планировал твитнуть "Сегодня расскажу про преимущества редакса" и целый день потом ничего не писать.

Традиционные слова поддержки. На этот раз от благодарных подписчиков.
notion image
notion image

Если серьезно, то преимущество редакса это иммутабельность. 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 кг за год

Традиционный обзор сентимента. Наблюдаем сильную поляризацию в обществе.
notion image
notion image

Победило тестирование. Начнем с обсуждения того, из-за чего чаще всего возникают баги на фронте. ⬇️

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$ каждый раз, когда я вижу такой код, то я был бы долларовым миллионером:
notion image

А как правильно? Можно было бы просто взять 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 Ну знаешь, передай мне намбер, а я скажу тебе намбер это или не намбер.
notion image

Тут можно возразить, типа "передай намбер, чтобы узнать инфинити это или нет". Но у нас нет метода 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 говорит мне, что я не могу задавать такой вопрос. Где массив создавали туда и обращайтесь.

Ясно понятно.
notion image

🔥Тред (Назим Гафаров)
А как там у нормальных пацанов? В 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. Запомните этот твит.
notion image

🔥Тред (Назим Гафаров)

Суббота


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

Сложно придумать какую-нибудь тему на сегодня, помимо политики. По политике в РФ каждый может сделать собственные выводы, поэтому давайте лучше расскажу о том, как и когда Китай загрузит детское порно на ваш компьютер. ⬇️

Многие не знают, что большая часть разработчиков 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
notion image

Ссылки