-
Разработка цифровых продуктов на современных технологиях и фреймворках с фокусом на финтех. Обсудить проект @YuraAndreev
Восстановление состояния после применения git push --force
📌 Применение git push --force может быть необходимым в ряде ситуаций, например, для коррекции ошибок в истории коммитов. Однако ее использование может привести к потере данных в репозитории. Как вернуть состояние до применения команды? Решение есть!
💻 Если вы не успели закрыть консоль, то в логах вывода находим строку вида:
+ deadbeef...f00f00ba master -> master (forced update)
git push --force origin deadbeef:master
Объединение интерфейсов в TypeScript
🔥 Сегодня рассмотрим одну замечательную возможность TypeScript — объединение интерфейсов, или merging interfaces. Этот механизм позволяет создавать более гибкие и масштабируемые типы.
🛠 Как работает объединение интерфейсов?
TypeScript уникален тем, что позволяет сливать несколько объявлений интерфейса в одно. Если вы объявляете два интерфейса с одинаковым именем, TypeScript автоматически объединит их.
interface User {
name: string;
age: number;
}
interface User {
email: string;
}const user: User = {
name: 'Алексей',
age: 30,
email: 'alexey@example.com',
}
Читать полностью…
Изучаем Array.prototype.flat()
Сегодняшняя тема посвящена одной из полезных функций, введенной в ECMAScript 2019, — методу Array.prototype.flat().
📚 Что такое Array.prototype.flat()?
Метод flat() позволяет «выровнять» многомерные массивы ранее заданной глубине. Это особенно полезно, когда вы работаете с массивами, структура которых может быть сложной или неизвестной.
🌐 Как работает Array.prototype.flat()?
flat() принимает один необязательный аргумент — глубину, которая указывает, насколько глубоко метод должен «выравнивать» массив. По умолчанию глубина равна 1.
Пример использования:
let multiDimensionalArray = [1, [2, 3], [4, [5, 6]]];
// Выравниваем на один уровень
let flatArray = multiDimensionalArray.flat();
console.log(flatArray); // Выведет: [1, 2, 3, 4, [5, 6]]
// Выравниваем на два уровня
let flatArrayDeep = multiDimensionalArray.flat(2);
console.log(flatArrayDeep); // Выведет: [1, 2, 3, 4, 5, 6]
CSS Logical Properties
CSS Logical Properties предоставляют альтернативу традиционным физическим свойствам, таким как width, height, margin, border, padding и подобным, для более адаптивного оформления веб-страниц. Они учитывают направление текста и другие языковые особенности.
CSS Logical Properties позволяют нам быть более гибкими в работе с мультиязычными интерфейсами и значительно сокращают количество кода, который нужно написать для адаптирования страниц под разные языки.
Вот несколько примеров использования.
Логические отступы:
.container {
margin-inline-start: 20px; /* Логический внутренний отступ слева (или справа) */
margin-block-end: 30px; /* Логический внутренний отступ вниз (в зависимости от направления текста) */
}.elent {
inline-size: 200px; /* Логическая ширина */
block-size: 100px; /* Логическая высота */
}.box {
border-inline: 2px solid #333; /* Логическая граница в горизонтальном направлении */
border-block: 1px dashed #555; /* Логическая граница в вертикальном направлении */
}.content {
padding-inline: 15px; /* Логический внутренний отступ в горизонтальном направлении*/
padding-block: 10px; /* Логический внутренний отступ в вертикальном направлении */
}
Привет, друзья!
Предлагаем сегодня решить такую задачку. Нужно вывести в консоль числа от 0 до 10. Как вы думаете, будет ли код на картинке работать? Напишите в комментариях: да/нет и почему?
@chulakov_dev
Всем привет!
Сегодня затронем важную тему — поверхностное и глубокое копирование в JavaScript.
Разберем, в чем разница между передачей данных по значению и по ссылке, рассмотрим разные способы копирования и расскажем, какие проблемы могут возникать при их осуществлении.
chulakov_dev/5nHdVVKilSY">Читать пост
@chulakov_dev
Инвариантность, ковариантность и контравариантность являются концепциями, связанными с типами данных в контексте обобщений. Они определяют отношения между типами данных при использовании обобщений.
Инвариантность
Инвариантность означает, что тип является неизменным относительно других типов. В контексте обобщений, если у вас есть обобщенный тип например MyType<T>, MyType<A> и MyType<B> не считаются связанными друг с другом, даже если типы A и B связаны отношением наследования.
Ковариантность
Ковариантность позволяет использовать подтипы вместо основного типа. Это означает, что если у вас есть обобщенный тип MyType<out T>, то MyType<A> является подтипом MyType<B>, если A является подтипом B. Ковариантные типы могут использоваться только в «выходных» позициях.
fun main() {
val producerA: Producer<A> = ProducerImplA()
val producerB: Producer<B> = producerA
}
interface Producer<out T> {
fun produce(): T
}
class A : B()
open class B
В этом примере Producer<A> является подтипом Producer<B>, поэтому мы можем присвоить producerA (тип Producer<A>) переменной producerB (тип Producer<B>).fun main() {
val consumerB: Consumer<B> = ConsumerImplB()
val consumerA: Consumer<A> = consumerB
}
interface Consumer<in T> {
fun consume(item: T)
}
open class B
class A : B()
В этом примере Consumer<B> является супертипом Consumer<A>, поэтому мы можем присвоить consumerB (тип Consumer<B>) переменной consumerA (тип Consumer<A>).
box-shadow VS drop-shadow
⚡️Привет! Сегодня разбираемся с разницей свойства box-shadow и фильтра drop-shadow.
Свойство box-shadow добавляет к блоку одну или несколько теней. Оно принимает либо значение none, что означает отсутствие теней, либо список теней, разделенных запятыми в порядке от переднего к заднему.
drop-shadow применяет эффект падающей тени к входному изображению. Тень представляет собой размытую смещенную версию альфа-маски входного изображения, нарисованную определенным цветом и расположенную под изображением. Значения интерпретируются как для box-shadow, но с опциональным третьим вариантом, который является стандартным отклонением, а не радиусом размытия.
📎 В чём же разница?
box-shadow дает нам тень, охватывающую весь элемент, даже если элемент не имеет фона.
drop-shadow применяется не к самому элементу, а к его визуальному представлению, включая прозрачные части и создает тень только от непрозрачных частей элемента. Помимо этого, drop-shadow не поддерживает ключевое слово inset, которое превращает тень из внешней во внутреннюю.
Радиус размытия в свойстве box-shadow в CSS определяет, насколько сильно тень будет размыта и растянута относительно элемента: чем больше значение радиуса, тем больше тень и тем меньше её чёткость.
С другой стороны, стандартное отклонение в drop-shadow аналогично радиусу размытия в box-shadow. Но, поскольку drop-shadow применяется к визуальному изображению элемента, эффект может выглядеть иначе, особенно если элемент имеет прозрачные области.
Пример использования:
.drop_shadow {
filter: drop-shadow(0 0 16px #000);
}.box_shadow {
box-shadow: 0px 0px 16px #000;
}
Читать полностью…
Этапы рендеринга в браузере
Давайте вспомним, как это происходит 🤓
1. Загрузка ресурсов (Loading): браузер загружает HTML-документ и связанные ресурсы, такие как стили CSS, скрипты JavaScript, изображения и медиафайлы.
2. DOM: из полученного HTML-документа формируется Document Object Model (DOM).
3. CSSOM: параллельно с DOM браузер обрабатывает стили CSS и формирует CSS Object Model (CSSOM).
4. Accessibility Tree: параллельно с DOM и CSSOM формируется Accessibility Tree, которое содержит информацию о структуре веб-страницы и ее элементах для вспомогательных технологий.
5. Render Tree: на основе DOM и CSSOM формируется дерево рендеринга (Render Tree), содержащее только видимые элементы и их стили.
6. Scripting: выполнение JavaScript, который может изменять DOM и CSSOM, что приведет к повторным процессам рендеринга.
7. Layout: браузер вычисляет положение и размеры каждого элемента в Render Tree (Layout или Reflow).
8. Painting: отрисовка элементов на странице на основе информации из Render Tree.
9. Composite: разбиение отрисованных элементов на слои и их объединение для формирования окончательного изображения страницы.
10. Оптимизация производительности и кеширование: применение методов оптимизации и кеширование для улучшения производительности загрузки и рендеринга.
11. Обработка событий: взаимодействие пользователя с веб-страницей может вызывать обновления DOM и запускать новые циклы рендеринга.
Понимание этих процессов позволяет разработчикам более точно дебажить и устранять проблемы с производительностью и совместимостью, а также эффективно применять передовые техники веб-разработки.
@chulakov_dev
Разбираемся в разнице: target="_blank" и target="blank" в HTML
🌐 Привет! Сегодня мы разберем интересный вопрос: в чем разница между target="_blank" и target="blank" при использовании в HTML? Детали могут показаться незначительными, но на практике они оказывают большое влияние на поведение ссылок в ваших веб-приложениях.
🎯 target="_blank"
Это стандартный способ открытия ссылки в новой вкладке браузера.
Каждый раз при клике на ссылку создается новая вкладка или новое окно браузера.
Пример использования:
<a href="https://example.com" target="_blank">
Открыть example.com в новой вкладке
</a>
<a href="https://example.com" target="blank">
Открыть example.com в именованном фрейме/вкладке "blank"
</a>
infer в примерах
Ключевое слово infer используется в контексте условных типов TypeScript для их автоматического вывода в определенных ситуациях и не может применяться вне расширения.
Эта конструкция языка позволяет нам определить переменную внутри нашего ограничения, на которую можно ссылаться или которую можно возвращать.
Другими словами, когда вы сталкиваетесь со сложными типами в TypeScript, infer помогает вытащить или определить неизвестные части этих типов, делая ваш код более гибким и легким для понимания.
Вы можете представить его как способ сказать TypeScript: «Выясни сам, какой здесь тип, и дай мне его использовать». Это особенно полезно, когда вы работаете с функциями или классами, где точные типы не всегда ясны из контекста.
Примеры применения ключевого слова infer.
1. Вывод типов из аргументов функции:
type ReturnType<T> = T extends (...args: any[]) => infer R ? R : never;
function add(a: number, b: number): number {
return a + b;
}
type Result = ReturnType<typeof add>; // Result будет иметь тип number
type actually = "123123123"
type Reverse<T extends string, R extends string = ""> = T extends `${infer Head}${infer Rest}`
? Reverse<`${Rest}`, `${Head}${R}`>
: R;
type result = Reverse<actually>; // "321321321"
Реализация типа Replace:
type actually = "912342181";
type Replace<T extends string, U extends string, R extends string = ""> = T extends ${infer Head}${infer Rest}
? Head extends U ? Replace<`${Rest}`, U, R> : Replace<`${Rest}`, U, `${R}${Head}`>
: R;
type result = Replace<actually, "1">; // "923428"
Продолжаем серию заметок про запуск проекта с использованием Strapi. В первом посте мы рассказали, как собрать свой образ Strapi, а во втором — как запускать его в docker-окружении. Сегодня мы настроим подключение Strapi к базе данных Postgres.
chulakov_dev/podkluchenie_Strapi_k_Postgres">👉🏻 Читать инструкцию
@chulakov_dev
Привет, друзья!
15-16 сентября в Ульяновске пройдет международная IT-конференция «Стачка», на которой выступит наш Frontend Team Lead Альберт Рыбалко с докладом «Таймеры в HTML5».
Спикер расскажет, что такое Host и почему он важен при работе с Web Api, подробно разберет работу таймеров и методы их очистки, а также объяснит, как микрозадачи выполняются в окружении JavaScript и какую роль они играют в асинхронном программировании.
Альберт выступит в секции «FrontEnd» 16 сентября.
@chulakov_dev