const transformObject = <const K0 extends string, const K1 extends string>(obj: Record<K0, Record<K1, string>>) => {
let result: Partial<Record<K1, Partial<Record<K0, string>>>> = {};
for (const key of Object.keys(obj) as K0[]) {
for (const lang of Object.keys(obj[key]) as K1[]) {
(result[lang] ??= {} as Partial<Record<K0, string>>)[key] = obj[key][lang];
}
}
return result;
};
От какого времени принято отталкиваться в программированииДелают и так и так, но лучше от UTC ибо стандарт и формально более точный, например учитывает високосные секунды именно в те дни, когда они были добавлены.
cfg(all(windows, target_env="msvc"))
var currentExtraStackFrame = null;
function setExtraStackFrame(stack) {
if (process.env.NODE_ENV === 'production') {
currentExtraStackFrame = stack;
}
}
В процессе сборки process.env.NODE_ENV
было заменено на 'production'
, а так как 'production' === 'production'
- это всегда истинное условие, то от if можно избавиться, оставив только его тело, вот только от блока при этом инструменты не избавляются, так как можно сломать видимость переменных. class PrevClickListener {
constructor(track, next) {
this.track = track;
this.next = next;
}
handleEvent() {
const {track, next} = this;
next.removeAttribute('disabled');
track.scrollTo({
left: track.scrollLeft - track.firstElementChild.offsetWidth,
behavior: 'smooth',
});
}
}
class NextClickListener {
constructor(track, prev) {
this.track = track;
this.prev = prev;
}
handleEvent() {
const {track, prev} = this;
prev.removeAttribute('disabled');
track.scrollTo({
left: track.scrollLeft + track.firstElementChild.offsetWidth,
behavior: 'smooth',
});
}
}
class TrackScrollListener {
constructor(track, prev, next) {
this.track = track;
this.prev = prev;
this.next = next;
}
handleEvent() {
const {track, next, prev} = this;
const trackScrollWidth = track.scrollWidth;
const trackOuterWidth = track.clientWidth;
prev.removeAttribute('disabled');
next.removeAttribute('disabled');
if (track.scrollLeft <= 0) {
prev.setAttribute('disabled', '');
}
if (track.scrollLeft === trackScrollWidth - trackOuterWidth) {
next.setAttribute('disabled', '');
}
}
}
const sliders = document.querySelectorAll('[data-slider]');
for (const slider of sliders) {
const track = slider.querySelector('[data-slider-track]');
const prev = slider.querySelector('[data-slider-prev]');
const next = slider.querySelector('[data-slider-next]');
if (!track || !prev || !next) continue;
prev.addEventListener('click', new PrevClickListener(track, next));
next.addEventListener('click', new NextClickListener(track, prev));
track.addEventListener('scroll', new TrackScrollListener(track, prev, next));
}
import { export as alias } from "module-name";
const PORT = process.env.PORT || 5000
const app = express()
const server = http.createServer(app)
server.on('upgrade', (req, socket) => {
// здесь websocket, можно использовать пакет ws
})
server.listen(PORT, () => console.log(`Server started on PORT = ${PORT}`))
(Foo|Bar)[]
позволит передать в себя массив, каждый элемент которого может быть как Foo так и Bar. Проверить тип всех элементов можно лишь пройдя итерацией весь массив.Foo[] | Bar[]
, в этом случае достаточно проверки элемента с индексом 0.#![feature(custom_test_frameworks)]
#[something]
применяются к айтему под ними, атрибуты вида #![something]
- к айтему в котором они находятся (должны находится в самом верху).app.use("/api", fooRouter, foooRouter, [fooooRouter, foooooRouter], fooooooRouter);