Pull to refresh
4
0
Алексей Мартинкевич @LEXA_JA

JS Developer

Send message

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

Typescript умеет переименовывать константные строки, как и находить на них ссылки

Если коротко, то из-за обратной совместимости. ЕМНИП раньше это было специфичное для какого-то браузера (IE6?) API. При этом использовались конструкции вида

if (document.all) {
  // old browser
} else {
  // new browser
}

Потом это дело решили стандартизировать и что-бы не сломать код добавили такой костыль.

VSCode тоже теперь такое подсвечивает

Ещё выдают лигатуры и линтер/форматтер.

Я постарался придумать пример с extends string. В данном случае мы используем литеральные типы. Это как раз type s = "name". Это тип которые соответствует не любой строке, а только строке "name". Использование для типизации CSS свойств например:
type CSSVisibility = "hidden" | "visible" | .... Или в сочетании с keyof:
const user = { name: "name", age: 25 }
function Pick<T, K extends keyof T>(o: T, key: K) {
return o[key]
}
const age: number = pick(user, "age")
const name: string = pick(user, "name")
Тут мы гарантируем что на объекте будет это свойство, и получаем тип возвращаемого значения.

Или ещё пример со склейкой строк в типах из какого-нибудь UI компонента:

type VerticalAlignment = "top" | "center" | "bottom";
type HorizontalAlignment = "left" | "center" | "right";
type Alignment = `${HorizontalAlignment}-${VerticalAlignment}`


Пример с ToHandler немного надуманный, но по идее такое может использоваться в сочетании с прокси. Мы берем объект и генерируем для каждого свойства хендлер, например для подписки на изменения свойства. Соответственно такое можно встретить в какой-нибудь библиотеке.

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

Нет, string | number не подойдет. Тут может быть как и просто string, так и строковый литерал, например Foo<"bar">

Вот пример использования:
Берем строку, разбиваем её на первый символ и всё остальное и собираем новую строку.

type ToHandler<Name extends string> = Name extends `${infer FirstLetter}${infer Rest}`
  ? `on${Uppercase<FirstLetter>}${Rest}Change`
  : never
type t = ToHandler<"name"> // "onNameChange"


На самом деле в прикладном коде писать что сложнее примитивных дженериков особо и не надо. Обычно такие вещи нужны для библиотек или переиспользуемых модулей.

Вообще на всё это можно смотреть как на программирование где типы - заначения а дженерики - функции.

> И почему-то частенько в описаниях пишут не T, а U extends T, но не объясняют, почему нам важны именно потомки типа. Типа, задел на будущее, чтобы функция работала с кем-то ещё?

Если я правильно понял то речь про код такого вида:
type Foo<T extends string> = { /**/}
или
type Bar = { /**/ }
type Baz<T extends Bar> = { /**/ }
В данном случае extends выполняет роль типов в обычных функциях, ограничивае типы, которые мы можем подставить.

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

В JS у нас один поток отправляет все запросы по очереди, не дожидаясь ответа. После этого мы ожидаем ответ, но в это время может выполняться другая задача. Когда ответ пришёл, обработчик попадает в очередь и выполняется.
Если я правильно понял, то в Java на каждый запрос создаётся поток. Поток отправляет запрос и ждёт ответ. Количество потоков ограничено. Соответственно одновременно отправляются не все запросы, а (условно) THREAD_COUNT. Если это так то при количестве запросов не превышающем THREAD_COUNT время будет +- одинаковое.
Ну и если мы займем потоки не IO а чем-нибудь CPU-bound то у Java будет преимущество.

Почему так

Из-за специфичности селекторов.
В первом случае у нас одинаковая специфичность селекторов, и приоритет у селектора, который был объявлен последним.
Во втором случае специфичность первого селектора выше, и порядок объявления не играет роли.

Это можно сделать за один проход и без ФП, через итераторы. Если не ошибаюсь, то в Rust такие вещи разворачиваются.
В JS это можно сделать через генераторы.

function* map(mapper, iterable) {
  for (const item of iterable) {
    yield mapper(item);
  }
}

function* filter(predicate, iterable) {
  for (const item of iterable) {
    if (predicate(item)) {
      yield item;
    }
  }
}

function reduce(reducer, initial, iterable) {
  let result = initial;

  for (const item of iterable) {
    result = reducer(result, item);
  }
}

reduce(
  (a, b) => a + b,
  0,
  filter(
    (x) => x > 2,
    map((x) => x + 1, [1, 2, 3, 4, 5])
  )
);

Наверное нужно смотреть в сторону WASM Text Format. Есть Спека. Не уверен, есть ли человекочитаемый гайд по нему, но вроде можно бинарный WASM перевести в текстовый формат.

Хуки это в первую очередь способ сделать независмый, переиспользуемый кусок логики привязанный к жизненному циклу компонента. Это замена для render props и HoC's (и ранне миксинов) в первую очередь. Со старыми методами была куча проблем, связанная с тем, что все общались через общие пропсы, конфликты имен и т.д. Просто хуки используются и как замена локальному стейту компонента, как в классовых компонентах.
Для IoC используется React Context. Вообще многие библиотеки выглядят в таком виде:

const client = new Client();

<ClientProvider.Provider client={client}>

{children}
</ClientProvider.Provider>
//
const client = useClient()


Есть класс отвечающий за логику. Он закидывается в компоненты через контекст. И есть хук который отвечает за привязку к жизненному циклу компонента.
Мне кажется в таком виде похоже на сервисы.

Если из статистико по Реакту убрать изучающих, то и из статистики по Vue/Angular тоже. Более того, количество интересующихся React'ом это тоже отражение его популярности.
Ещё можно глянуть на колучество вакансий по фреймворкам. У меня вышло соотношение примерно 6.5/3/1 React/Angular/Vue

transform меняет только позицию при смене состояний - on/off/indeterminate. А grid отвечает именно за изначальное позициониирование элемента относительно родителя. Он как-раз про это говорит на 10:39.

Обещали нативный запуск андроид приложений, но, похоже, в этот релиз не вошло.

Если я не ошибаюсь, grid используется для позиционирования ::before вместо традиционного position: absolute.

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

В случае с анимациями - была панель уведомлений и анимации на появление\скрытие новых уведомлений. Уведомления убиралась по клику или таймауту. Таймаут сбрасывается при добавлении новых уведомлений. По итогу лапшу с кучей if, переписал на простую таблицу состояний\переходов.

Использование для вложенных диалогов или многоэтапных форм. Удобно описать весь граф переходов как FSM.

Комнада реакта писала про мотивацию. Хуки пришли на замену render props и частично HOC, или ещё более древним миксинам. Они решают следующие проблемы:
Композиция — в хуки легко прокинуть данные, получить из них данные и засунуть из в другой хук. https://github.com/acdlite/recompose для сранения, как было до хуков.
Легко использовать несколько инстансов одного хука.
Нету конфликтов, когда засоряется общее пространство имен в props.
Плюс ещё функции лучше минифицируются, чем классы.
Всё это хорошо работает с typescript, в отличие от того, что было.
И ещё что-то там про то, что новички испытывали проблемы с классами и this.


Если подытожыть — то это лучший на текущий момент подход.

Information

Rating
Does not participate
Location
Гродно, Гродненская обл., Беларусь
Date of birth
Registered
Activity