Как стать автором
Обновить
4
0.2
Отправить сообщение

Интересная статья, спасибо.

Применение any вместо never в качестве типа по умолчанию — вынужденная необходимость из-за ограничения T extends P, вытекающего из природы тайпгарда

можно заменить на unknown

В нашей реализации есть что улучшать. Например, можно попробовать ввести обобщенный тип S, как и в других примерах, чтобы на этапе компиляции отсекать бессмысленные проверки, которые априори ведут к пустому массиву.

Это стоит сделать, потому что прямо сейчас добавление "лишнего" пункта в someOf молча ломает типизацию, и фильтр перестает работать в режиме тайпгарда. Если в самом последнем примере добавить в копилку, допустим, is(2), то filtered будет Event[]

Допилил этот кейс, небольшие изменения в строках 41-48

в этом примере несколько другое. А именно, что конкретно брать за "N" в О-большом. Если длину стороны матрицы, то так и будет O(N^2)

Только если соседние элементы различаются на единицу. В задаче нет такого условия.

Правило 4 применимо для простого кейса - когда сложность внутреннего цикла не зависит от текущей итерации внешнего. Если зависит, то придется аккуратно просуммировать сложности, и там может выйти по разному. Например, в пузырьковой сортировке так и остается O(N^2), а вот для того же heapify внезапно оказывается O(N)

Можете кинуть ссылку на Playground с ошибкой?

Не очень понял, как это можно использовать.

Ну, например, GetWithArray < ProductionObject, ['versions', 'length'] > должен быть number - берем длину массива.

Я тут слегка поправил своё решение, точнее ExtractFromObject . В предыдущем были косяки с кортежами и массивами:

1) для кортежа ключ number возвращал все свои значения без undefined, а должен с ним.

2) неправильно работало с ключами-объединениями для массивов (см. примеры в extendedCases), в том числе never. Ключи never срезают всё кроме null и undefined, т.к. эти двое не индексируются.

3) для массива ключ never возвращал все его значения (думаю, это баг TS), а должен вернуть never, как в объектах

Я вот так решил:

type ExtractFromObject<O, K> = [never[], K] extends [O, number | `${number}`]
  ? O[number & keyof O] | undefined
  : K extends keyof O ? O[K] : undefined;

type GetWithArray<O, K> = O extends null | undefined
  ? O
  : K extends readonly []
    ? O
    : K extends readonly [infer Key, ...infer Rest]
      ? GetWithArray<ExtractFromObject<O, Key>, Rest>
      : never;

У вас не совсем правильно работает на массивах, например, у массивов есть свойство 'length', которое должно быть number.

Выкидывать null и undefined можно с помощью типа NonNullable < T >, который под капотом просто T & {}. Почему так? Потому что {} - это "всё кроме null и undefined"

вызов showSuccess и showFailure ошибочно соседствуют рядом с декларативным подходом

Специально для этого кейса у хука useQuery есть целых 3 параметра - onError, onSettled, onSuccess

"нет" и "наверно да" )

Там решил чуть более 500 паззлов. Сколько по времени - непонятно, бывал в основном набегами, в 10х гг. Сейчас обленился, не решаю)

в задаче 11 использован "принцип включения-исключения"

Помнится, такая задача, вместе с ещё двумя, попалась мне на очном собесе в майлРу в 2016. Все три уже были ранее решены на braingames.ru, и целых 20 минут я усиленно изображал работу мысли в поисках решения :)

Название ref устоявшееся, традиционное. А useImperativeHandle дополнительно может работать с рефом в виде функции, и обнуляет его при размонтировании (заодно отметим, он работает на том же этапе, что и useLayoutEffect, т.е. не будет сюрприза, если мы сами вдруг захотим использовать api в useLayoutEffect).

Нет требования, чтобы в useImperativeHandle закидывать именно реф, который пришел из forwardRef - подойдет любой реф.

Наиболее любопытный момент всей истории - extends для параметра ApiGetter в типизации хука useApi. Эта штука позволяет "заморочить голову" тайпскрипту и выключить проверку возможности вызова для api(config ?? {}, params ?? {})[ method ] (...), в чем легко убедиться - result имеет тип any. По факту "методом" может оказаться любое значение, но если это не функция, то для её вызова понадобится аргумент типа never, т.е. вызвать нельзя, TS тут защищает не напрямую, но косвенно. Для более явного ограничения можно написать

Method extends {
    [K in keyof ReturnType<ApiGetter>]: ReturnType<ApiGetter>[K] extends (...args: never[]) => Promise<HttpResponse<unknown>> ? K : never;
  }[keyof ReturnType<ApiGetter>],

и теперь в method станет дозволено передать только такое название поля, за которым стоит функция, возвращающая промис HttpResponse

ТипоСкриптъ

Машинопись же

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

семь человек одну и ту же несложную задачу могут написать на нём семью различными способами

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

Интересно, в этих графиках пользователи TypeScript - это подмножество пользователей JavaScript, или разные?

У нас ещё есть "безусловный" аналог useCallback

import {useCallback, useInsertionEffect, useRef} from 'react';

export function useEvent<T extends (...args: never[]) => unknown>(func: T): T {
    const refCallee = useRef(func);

    useInsertionEffect(() => {
        refCallee.current = func;
    });

    return useCallback((...args: never[]) => refCallee.current(...args), []) as T;
}

Подходит для всех кейсов, кроме вызова на этапе рендера или в useInsertionEffect в каком-нибудь чилде. Любые колбэки, обработчики событий, (layout)эффекты и т.д.

Тема разобрана здесь

свидетели MobX налетят на вас толпой и будут хэйтить...

...за невнимательное чтение документации. Устав нашей секты такое не приветствует!

https://www.npmjs.com/package/zustand#using-zustand-without-react

Информация

В рейтинге
2 136-й
Откуда
Москва, Москва и Московская обл., Россия
Зарегистрирован
Активность

Специализация

Frontend Developer
Senior
JavaScript
TypeScript
React
HTML
CSS
Web development
Redux
MobX
Webpack