Search
Write a publication
Pull to refresh
2
0.2
Send message

Т.е. для number Boolean не является корректным предикатом типа.

Так он проверяет не на число, а на "nonfalsy". То есть правильная тайпгардная типизация внутри BooleanConstructor была бы примерно такая:

<T>(value?: T): value is Exclude<T, null | undefined | 0 | 0n | '' | false>;

Любопытно, что если добавить эту сигнатуру в BooleanConstructor через слияние интерфейсов, то напрямую тайпгард начинает работать (if (Boolean(v)) { ... v ... }), а в filter не подхватывается

Когда у нас значение 0, то Boolean возвращает false. Поэтому Boolean не является корректным предикатом типов для number

Почему? Boolean отсеивает значения undefined и null, и вполне мог бы быть, например, тайпгардом (x: number | undefined) => x is number. Но он протипизирован не как тайпгард, а как обычный предикат, потому и не выкидывает undefined и null, как при вызове напрямую, так и через filter.

В версии 5.5 просто добавили несколько эвристик, по которым в ряде случаев не заданное явно возвращаемое значение функции будет выведено как предикат типа, а не просто логическое, например const isNum = (x: number | undefined) => x != null;. К случаю с Boolean это не относится

С пунктом 4 есть ещё более интересный прикол. Да, в object напрямую не засунуть примитив, но можно так:

const nn: {} = 1;
const obj: object = nn;

То есть object оказался надтипом для более широкого {}, что идет вразрез с иерархией типов.

П.3 широко известен, во многих библиотеках есть его исправление, добавляющее перегрузку для метода filter.

П.5 - следствие ковариантности изменяемого массива, добавленной для удобства и в своё время вызвавшей много споров.

Из тех, кто в июне 1941 зашел на территорию СССР, большинство были патриотами, причем довольно упоротыми.

Наверно, им ещё гарантировали нормальную бронь от мобы, если в нужный момент "ничего не сломается".

Относительно решения: кажется, для второй компоненты надо брать не 24, а 26. У нас тут 7 ребер, надо выкинуть 3 из них. Всего вариантов это сделать С(7, 3) = 35, "плохих" вариантов 9 штук: 4 тройки ребер, смежных с 4 вершинами, и 5 троек, в которых два ребра смежны с пятой вершиной. Итого 35 - 9 = 26

Для асимметричной монеты есть еще такой паззл: надо бросить честный жребий на 5 чел., но мы имеем право на старте выбрать и зафиксировать p (и q = 1 - p) по своему разумению. Придумать это самое "p" и алгоритм, чтобы гарантировать результат не более чем за N бросков (чем меньше N, тем лучше, знаю решение за N=5)

UFO landed and left these words here
UFO landed and left these words here

Итого, N мышей могут проверить 2^N колб. Но это за 1 раунд, то есть когда есть запас времени всего 1 час. А если у нас К раундов, т.е. К часов? Как обобщить?

Тогда можно проверить (K+1)^N колб. Номера колб представляем в (K+1)-чной системе счисления, это будет число из N разрядов, возможно с нулями впереди, чтобы было ровненько. Каждая мышь отвечает за свой разряд. На i-м раунде (i = 1..k) мышь с номером p пробует из тех колб, в номере которых p-я цифра равна i. Если погибла, то в номере искомой колбы p-й разряд равен i.

Кстати, всегда еще было интересно отчего у человека, в отличии от животных, волосы не перестают расти в длину

Причем это так только на голове

При его строительстве особенно чувствуется разница между тем как TS обрабатывает length у кортежей и у строк шаблонных литералов с известной длиной.

Это только запутывает читателя - непонятно, почему нельзя использовать результаты с предыдущей итерации (точнее, частично можно, а частично нет). Длину мы всё равно смотрим у счетчика Count. Соответственно, у конструируемого значения не обязательно должен быть какой-то свой "показатель длины", и неважно, как мы получаем значение на новой итерации. Просто в первом примере мы собирали кортеж и могли смотреть длину прямо у него, поэтому отдельный вспомогательный счетчик был не нужен. А когда делаем строку (или, например, дерево заданной глубины, или ещё что-то), приходится использовать вот этот прием с отдельным счетчиком.

Тут на самом деле без разницы. TS всё равно превращает это в объединение строковых литералов, потому что Digit - конечный набор значений. Просто делается декартово произведение, и всё. Посмотрите в плейграунде результат, по наведению мыши.

Странный какой-то комментарий. В статье говорилось о контравариантности параметров, и флаге strict, для того чтобы это нормально проверялось. Причем тут перегрузки?

Не понял, в чем затруднение, у меня всё норм. работает

BuildHexString не совсем соответствует своему jsdoc, он здесь дает строки длиной от 1 до N включительно. Если нужна длина ровно N, то надо убрать Result | из рекурсивного вызова. Ну и разумеется, тут не надо возиться с созданием кортежа и последующим join, проще сразу конкатенировать шаблонную строку, длина всё равно считается отдельным кортежем Count:

type _BuildHexString<N extends number, Result extends string, Count extends unknown[]> = Count['length'] extends N
  ? Result
  : _BuildHexString<N, Result | `${Result}${Digit}`, [1, ...Count]>;

Ещё можно добавить, что, несмотря на вложенный цикл, там O(n) по времени, потому что во вложенном цикле делается снятие со стека, а каждый элемент добавится в стек один раз, итого суммарно n внутренних итераций.

1
23 ...

Information

Rating
5,237-th
Location
Москва, Москва и Московская обл., Россия
Registered
Activity

Specialization

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