xycu2.rar
51 subscribers
106 photos
6 videos
13 links
Download Telegram
Официально стартуем TypeScript 👨‍💻⚡️
🔥2
Учимся кастовать типы в TS и заставлять компилятор верить нам на слово!

Конструкция as unknown as Type. Она позволяет сбросить текущий тип и принудительно навязать свой.
1
красиво 🙂‍↔️
👍1
Перевожу проект с JS на TS. Наконец-то нормальный автокомплит в шаблонах Vue и никаких гаданий по поводу структуры данных.
Теперь редактор кода подсказывает какие свойства есть и какой должен быть тип
Когда пообещал себе за субботу переписать всё на TypeScript и реально это сделал 💻🔥

Целый день сидел в коде, переписал все компоненты и логику. Итог на скрине!
Технически JS тут еще на 4.7% остался только из-за конфига Vite, так что можно считать, что миграция завершена на 100%.
🔥1
Паттерн Assert Exhaustiveness в TypeScript: заставляем TS искать баги за нас

Представь: у тебя есть union-тип статусов заказа или валют, и ты обрабатываешь их через if или switch. Что произойдет, если через полгода в проект добавят новый статус, а ты забудешь добавить его обработку в функцию? Код тихо вернет undefined и сломает интерфейс.

Чтобы этого избежать, используется паттерн Assert Exhaustiveness:
type Currency = 'RUB' | 'USD' | 'EUR' // Добавили EUR

// Вспомогательная функция для проверки исчерпываемости
// "value: never" работает в редакторе , и подсвечивает ошибку, если не обработали вариант
function assertExhaustiveness(value: never): never {
// Работает на сервере
throw new Error(`Необработанный вариант: ${JSON.stringify(value)}`);
}

function getCurrencyChar(currency: Currency) {
if (currency === 'RUB') return '₽';
if (currency === 'USD') return '$';


// ТУТ TS ВЫДАСТ ОШИБКУ КОМПИЛЯЦИИ:
// Argument of type 'string' (EUR) is not assignable to parameter of type 'never'.
// TS буквально заставляет тебя написать еще один if для 'EUR'!

// Если все варианты обработаны, сюды доходит только 'never'
return assertExhaustiveness(currency)
}
1
Заметки по TypeScript в порядке 🧠

Постепенно закрываю базу и переходные темы. Порядок в Obsidian — порядок в голове.
Перегрузки функций в TypeScript:
// Реализовываем перегрузку
function axios(url: string): string;
function axios(url: string, sett: { method: string }): number;
function axios(sett: { url: string; method: string }): string;

function axios(urlOrSett: string | {url: string, method: string}, sett?: {method: string}): string | number {
if (typeof urlOrSett === 'string') {
if (sett) {
return 200; // Case 2: url + sett => number
}
return 'Data from URL'; // Case 1: url => string
}

return 'Data from config'; // Case 3: config object => string
}

const a1 = axios('/url')
const a2 = axios('/url', { method: 'GET'})
const a3 = axios({url: '/url', method: 'GET'})

Представьте, что функция может принимать разные варианты аргументов (например, просто string или объект настроек).
Если просто написать function axios(...): string | number, TypeScript вернет тип string | number при любом вызове. В итоге придется везде писать лишние проверки if (typeof ... === 'string')

Перегрузки функций решают эту проблему! Они задают четкое правило:
Если передали аргументы типа A — возвращаем строго тип B, а не неопределенный union!
👍1
Дженерики в TypeScript делают код гибким, но иногда эту гибкость нужно ограничить. Для этого используется extends (Generic Constraints).
В примере ниже мы явно говорим компилятору: T может быть чем угодно, НО только из числа string или number.
// extends сужает(ограничивает) типы данных в дженерике
// мы можем вызывать эту функцию только со строками или числами
function wrapInArray<T extends string | number>(value: T): T[] {
return Array.isArray(value) ? value : [value];
};


// Все работает
wrapInArray(1);
wrapInArray('hello');

// Ошибка: мы не можем вызывать с типом данных boolean
// wrapInArray(true);

В итоге мы получили безопасную функцию, которая не принимает лишний мусор вроде boolean или объектов, сохраняя при этом точную типизацию возвращаемого значения. 🔥
Репозиторий создан, окружение поднято — к работе готов! 🚀 Начинаем переписывать приложение с чистого HTML/JavaScript на Vue 🥳
Сегодня занимаемся TypeScript:
Закрыл блок по Generics в TypeScript! 🚀

Сегодня полностью добил дженерики и разложил всё по полочкам в Obsidian.
Прошёл путь от базового синтаксиса до продвинутых вещей:

1) Generics в функциях, классах, type и interface
2) Ограничения (Generic Constraints) и связка с keyof, typeof, Exclude
3) Константные дженерики (<const T>) и их применение в типизации роутинга

Двигаемся дальше! 💻🔥
Полезная кастомная утилита в TypeScript: ValueOf

В TypeScript из коробки есть утилита keyof, которая достаёт все ключи объекта в виде Union-типа. Но встроенной утилиты для получения значений нет.
Чтобы не писать это каждый раз вручную, создаётся простой и универсальный дженерик ValueOf:

// Дженерик для получения всех типов значений объекта / интерфейса / типа
type ValueOf<T extends Record<string, unknown>> = T[keyof T];

Как это работает:
1) extends Record<string, unknown> — ограничивает входящий тип T, разрешая передавать только объекты.
2) keyof T — получает Union всех ключей объекта.
3) T[keyof T] — возвращает Union всех значений, соответствующих этим ключам.
Красота TypeScript + Замыкания в JS 💡
Разбирал пример на курсе и поймал классный инсайт о том, как красиво пересекаются JS-фундамент и система типов TS.
Написали фабричную функцию customService, которая принимает массив ключей:
function customService<const T extends string[]>(keys: T) {
function save<D>(key: T[number], data: D) {
// logic...
}

function getData(key: T[number]) {
// logic...
}

return { save, getData }
}

const serviceUtils = customService(['userId', 'videoId']);
serviceUtils.save('userId', {});
serviceUtils.getData('videoId');
// serviceUtils.getData('postId') // Ошибка TS!

В чём тут фишка:

1. Замыкание в JS: Вложенные функции save и getData удерживают доступ к области видимости customService даже после её выполнения.
2. Замыкание в TS: На уровне типов происходит то же самое! Тип T запекается при вызове внешней функции (['userId', 'videoId']), а внутренние функции через T[number] "замыкают" этот тип и превращают его в строго ограниченный Union 'userId' | 'videoId'.
3. const T (TS 5.0): Позволяет не писать as const при вызове функции. TS сам выводит массивы как точные readonly-кортежи.

Получился идеальный автокомплит и полная типобезопасность без лишнего кода 🔥
Прокачиваю свои CLI-инструменты 🛠

Раньше для отправки кода на GitHub я пользовался обычным дефолтным .bat скриптом из трех команд. Но сегодня решил, что пора избавить себя от рутины, и начал писать полноценную интерактивную утилиту.

Что будет уметь новый скрипт:
⚙️ Интерактивное меню с выбором действий (choice + goto)
⚙️ Быстрый push с вводом кастомного коммита
⚙️ Первичная инициализация репозитория и привязка remote в один клик
⚙️ Быстрое создание и переключение веток.

На скрине сравнение старого скрипта и заготовки для нового. Допилю логику, поправлю пары мелочей и выложу готовый скрипт, если кому-то пригодится! 🔥