Ви плутаєте терміни «хвостова рекурсія» та «оптимізація хвостової рекурсії». В компіляторі тайпскрипту відсутне друге, а перше можна запросто створити
Тому я і написав, що написав:
твердження «в TS немає хвостової рекурсії» — це брехня
правдиве твердження: «TS компілятор* не виконує оптимізацію* хвостової рекурсії»
Аххахаха, чел, я в TS не можу написати так:
function factorial(n: number, acc: number = 1) { if (n <= 1) return acc; return factorial(n - 1, n * acc); }
це хвостова рекурсія, прикинь. Те, що компілятор її не оптимізує це не значить, що її не існує, і не значить що TS нефункціональна мова. Це значить рівно те, що значить: в TS відсутня TCO.
Спроба з цього факту зробити сенсацію лише демонстрація власного невігластва
у вас, як у інженера має бути добре розвинене абстрактне мислення та ви маєте чітко та добре відчувати та розуміти різницю між «never — це пуста множина» та «never та пуста множина мають багато спільних рис». Але якщо ви пишете такий коментар — то скоріше за все ця різниця опинилась за межами ваших книжок та вашего IDE
Доречі пуста множина також має властивість еквівалентну bottom типу
Нічого.
нарешти зізнались, що нічого конструктивного донести навіть і не намагались. Думав не дочекаюсь
Очевидно, що за весь час дискусії ви не змогли нічого сказати нового окрім купи дивних тез без доказів, ще і по 4 рази повторили, щоб всі зрозуміли, що ваші книжки вам не допомгли
Нуль аргументів, чому в ТС нема хвостової рекурсії
Нуль аргументів, чому ТС нефункціональна мова
Нуль аргументів, чому теорія множин не потрібна в ТС
Як мантру повторюєте одне і те саме, в надії, що я з
Я пишу це без жодної агресії чи з метою принизити. Зрозуміло, що для звичайного Go/Python/Node розробника, який вміє бездоганно писати код на домофоні сосєда без жодного UI, правильно підбирати слова та розуміти щось в там в теорії множин та кванторах — це занадто по-хіпстерськи та недостатно брутально
А ви що довести питаєтесь? Кінцева мета яка? Що DX це «блажь буржуазних зумєров», як не можуть самостійно лінійний пошук без копілоту написати? Так ви неправі повністю, навіть не намагайтесь сюди лізти
Приклад що ви навели — едж кейс, цим не можна щось аргументувати
Тим паче ви так кажете, що якщо ви щось складніше ніж as any напишите, то у вас закінчиться оперативна памʼять на вашому М12 Pro Ultra Max на 512 ОЗУ. Це не правда. Щоб ваша IDE стала повільною — це прямо треба постаратись зробити (хоча я впевнений, що у вас вийде запросто)
Не відходьте від бази: будь-який більш менш простий API вимагає мінімум x2 типізації і все. І це важливо для того, що API можна було нормально користуватись і воно було type safe. DX вже іде бонусом, це не самоціль
Боже, ви прочитали 1000000 книжок але вам це не допомогає
твердження «в TS немає хвостової рекурсії» — це брехня
правдиве твердження: «TS компілятор* не виконує оптимізацію* хвостової рекурсії»
також брехня: «відсутність TCO робить мову нефункціональною», адже функціональність мови ніяк не залежить від того, які оптимізації може робити конкретний компілятор.
Якщо б ви хоч трохи були обізнаними в темі, ви би могли зауважити: ось TS не підтримує High Order Types, тому це не функціональна мова програмування на рівні типів*. Але куди вам там до того — так само як обходите граматику SQL діалектів, ось так сама формальна логіка вирішила обійти і вас
по-моєму очевидно з того, що написано раніше, що я написав з помилкою:
Тому тезіс «теорія множин не потрібна* для глибшого розуміння мови програмування» — хибна
І я не вірю, що ви цього не зрозумілі, якщо ви взагалі читаєте те, що я пишу, бо там з контексту все очевидно. Ви
Ні, не випливає.
Так а навіщо ви тоді то написали, якщо це ні на що не впливає? Щоб всі дізнались, що ви книжки читаєте?
Дякую за цей семпл коду! Безцінний вклад в розкриття теми. Пункт про те, що вичерпний масив
Трохи дописав, щоб працював з union-ами, використовуючи тип Tuple:
type LanguageOption = "en" | "fr" | "us" | "uk"; type LanguageOptions = Tuple<LanguageOption>; type ExhaustiveArray<U> = GeneratePermutations<Writable<Tuple<U>>>; const test: Array<LanguageOption> = ["en", "fr", "uk", "us"] satisfies ExhaustiveArray<LanguageOption>;[Playground link][www.typescriptlang.org/...YUoFt 3nCwJ3w-wSOzYtq2gA
давайте без діагнозов, і ви повторюєте одне і те ж саме
«в жодній сучасній мові програмування виведення типів не працює поверх теорії множин» — де я доводив наступне? ви взагалі читали, що я написав?
давайте прочитаємо разом: «типи в тс не множини» !== «теорія множин не потрібна для глибшого розуміння мови програмування», що правда, адже якщо ставитись до типів як до множин, то можна зайти багато перетинів з теорією множин і з дискретною математикою в цілому — і це правда. Тому тезіс «теорія множин для глибшого розуміння мови програмування» — хибна.
Приємно доречі, що в свому коментарі ви навіть не намагаєтесь це «опровєргнуть».
Ну і ще раз, уявимо, що ви праві, і що тоді випливає з цього? Випливає, що для глибшого розуміння TS замість теорії множин необхідно знання системи Хіндлі-Мільнера, формальної логіки, теорії типів, лямбда-калкусу — супер! Оберіть собі хоча б одно з цього списку та вивчить, обіцяю вам зробити те ж саме зі свого боку
дійсно яка різниця. Пропоную все типізувати завжди як unknown і ставити 150000 type guard-ів та асерторів, адже взагалі будь що може бути будь чимось
після «перетворить на масив ключ title» можна більше ваші слова про антипатерни в серйоз не сприймати, адже більшого пострілу в ногу, про які ви так любите казати — важко вигадати
Мапінг як чиста функція* Більш того обʼєкт мапінгу також можна вважати чистою функцію — згідно до теорії множин це повноцінне функціональне відношення
Дякую за інформацію.
В будь-якому разі це не скасовує валідність першого та третього пунктів: 1 — це не фіча. 3 — це просто анти-паттерн та не зручно
Чудова стаття, дякую! Особливо сподобалось як ви розришили RequestInit — вміння працювати та робити перетворення над вже інсуючими типами є важливим скілом TS дева
При цьому хотів би зауважити, що деякі елементи можна і треба покращити:
1. використання enum для API — семантично enum точно не для такого типу даних. Зазвичай такі речі лежать в конфізі або оголешні як as const обʼєкт
2. неймінг: префіксувати назви інтерфейсів з I — відверто принаймні бєсполєзна практика, це нічого не дає, і є сліпою даниною поганої традиції C#. Назви інтерфейсів мають бути дієсловом у теперішньому часі: IsRequestInit, IsArray або принаймні починатись з ’With’ і так далі, щоб показувати, щоб підкреслювати семантичну роль інтерфейсу як контракту
3. третє — тут взагалі непотрібно думати про неймінг інтерфейсу, адже існуючи інтерфейси необхідно розширювати за рахунок Interface Merging та Module Augmentation:
declare global {
interface RequestInit {
body: any;
}
}
небачу нічого поганого в тому, щоб думати про DX. Все ж таки живемо в 2024 а не в 1984 і маємо змогу писати код не в терміналі домофона
Прикольний підхід, мені подобається,
але все одно ж у вас direction буде типізовано як ltr | rtl
і знову ж таки id мов ви би також типізували як union допустимих значень — мапінг нікуди не дівається де-факто
при цьому знову ж таки, мені в різних UI можуть бути потрібні різні варіанти тайтлов, і більш того — інший порядок мов, то мені все одно доведеться використовувати мапінг
Мапінг — це лише окремий випадок чистої функції. Я не вважаю справедливим та коректним вважати цілу підмножину функцій «безглуздим рішенням» та «антіпатерном»
для створення API
наприклад ви хочете створити route loader для ReactRouter
і у вас таке api:
createBreadcrumbRouteLoader = (route: R, params: InferredRouteParams) => Promise
в рантаймі React Router буде в парамс класти значення path params, але по замовчуванню ви не отримуєте автокомпліт, бо params будуть Record, а цей тип дозволить отримувати type safety + приємний автокомпліт
Можна обійтись без цього, зробивши прямий assertion params, але знову ж таки — це не значить що InferredPathParams «бєсполєзний».
Ще раз: коли ви хочете створити ± просте та приємне API, щоб правильно описати його типо виведення потрібно буде трохи напрягтись і базовим TS тут не обійтись
Ви б так і почали з того, що ви просто не любите TS і заощадили кучу б часу мені)
В статті прямо сказано, що до EnumArray немає вимоги до унікальності і пояснено чому
І це жодним чином не ставіть цінність самої статті під питання, адже стаття має за мету створити ExhaustiveArray
Крута стаття, дякую! Добре, що хтось підіймає таку тему як важливість POC в циклах розробки, а то з тим як стихійно та «з наскоку» розвивається більшість проєктів, приємно знати, що ще є команди та компанії, які цінують свій час та ресурси і професійно та ґрунтовно підходять до розробки продукту