Стендап Сьогодні
📢
Канал в Telegram @stendap_sogodni
🦣
@stendap_sogodni@shevtsov.me в Федиверсі
Пости з тегом #TypeScript
13.03.2025
Про переписування
Всі, мабуть, вже чули про компілятор TypeScript переписують на Go. Хотів прокоментувати з позиції людини, яка багато чого переписувала, в тому числі й на Go.
Вони обрали найпростішу форму переписування - 1-до-1. Чудово, що була така можливість, бо не така вона вже й “найпростіша”. Переписати один модуль то вже важко, а тут величезний проєкт. Проте принаймні не доводиться адаптувати структури даних та ієрархію коду під іншу парадигму.
Власне, переписувати 1-до-1 гарно, якщо мови мають схожі парадигми. В разі TS це ще й залежить від стилю програмування; якби код був більш функціональним, навряд чи вдалося б його адаптувати через те, що Go змушує прописати типи кожної функції явно. Але, наскільки я знаю TS, там більш-менш імперативний код, не такий далекий від Go.
Але разом з тим їхній код на Go не такий вже ідіоматичний. Яскрава ознака для мене: бачу лише 125 місць, де з функції повертається error. Також багато структур, що складаються із функцій — теж ідіома з JS, а не Go. Втім то все можна виправити, головне з чогось почати.
До речі, Microsoft не вперше цікавляться Go - в них є навіть власний форк заради якихось вимог криптографії, які мені важко зрозуміти. А сьогодні дізнався про такий проєкт як [Dapr]https://github.com/dapr/dapr) - теж від Microsoft.
А взагалі, я дуже радий тому, що відбувається: одна з моїх улюблених мов переписана на іншу. 🥳
15.10.2025
Міст з узагальненими типами на TypeScript
У Firebase, окрім стандартного для JavaScript пакету firebase, є також неофіційний пакет React Native Firebase. Він побудований на “рідних” інтеграціях для iOS та Android, а тому має переваги саме на мобільному пристрої.
От тільки є проблема: хоч RNFirebase майже збігається зі стандартним Firebase за API, але типи для TypeScript оголошує власні. Що з одного боку логічно, бо кожен має власну реалізацію цих типів — наприклад, і там, і там є клас CollectionReference. А з іншого — унеможливлює написання спільного коду, що буде працювати й в браузері, і в React Native. Або чи правда унеможливлює?
(Окремим аспектом тут є те, що не так давно Firebase перейшов з класового API на функціональний. Тобто замість app.firestore().collection("path") тепер є collection(getFirestore(app), "path"). Що і спрощує, і ускладнює задачу.)
Отже, що я зробив? Для початку, весь шар, який звертається до Firebase, в мене прихований в клас. Методи цього класу працюють вже з простими обʼєктами. Можна було б на цьому й зупинитися, розставити всередині класу примусові типи.
Якщо трохи серйозніше ставитись, то можна тепер зробити дві версії класу. Кожна буде імпортувати відповідний пакет та мати всередині повністю сумісні типи. Це реалізація якогось там патерну, не памʼятаю якого. Але доведеться повторити купу коду. (Та й, очевидно, підтримувати в майбутньому.)
Тому знайшов ще краще рішення — оголосив інтерфейс (насправді в ньому більше й параметрів, і методів:)
interface FirebaseAPI<CollectionReference> {
collection(path: string): CollectionReference;
}
class FirebaseLayer<CollectionReference> {
constructor(api: FirebaseAPI<CollectionReference>) {}
}
export let firebaseLayer: FirebaseLayer<unknown>;
Тепер залишається окремо для мобільної та вебверсії реалізувати інтерфейс з конкретними типами та передати цю реалізацію в шар абстракції. А решта коду зовсім не цікавиться тим, які конкретні типи всередині.
Так вийшло мати на 100% покритий типами код та, можна сказати, мінімум повторення (а повторення все ж є, бо реалізації інтерфейсу майже однакові.)

