Брио?
Брио — это сенсационное слово, и мы должны использовать его чаще, я изучал то, что изучал о системах типов, только из-за брио, которое я имею для такого рода контента (парсеры, компиляторы и так далее).
Я увидел этот код и как человек с гордостью прочитал его, пока не понял, и сегодня я могу объяснить хоть немного о системах типов
Суть этого кода находится здесь
Что такое система типов?
Система типов, как говорит наша википедия, — это система типов:
é um conjunto de regras que atribuem uma propriedade chamada de tipo para as várias construções
Но что это значит в конце дня? Это правила, которым мы должны следовать, например, надевать гири на ноги, как рок-ли (да, это поможет нам, поверьте).
Когда мы собираемся работать в более зрелых кодовых базах с кодом, который имеет четко определенные типы, мы уверены с помощью тестов, что этот код работает так, как должен. Типы помогают проводить статический анализ кода.
Сегодня мы поговорим о том, как играть и мучить систему типов TypeScript и узнать больше о том, как программировать лучше и об основах языков программирования в целом.
TypeScript
Прежде чем говорить о коде, я прокомментирую, где находится typechecker и некоторые курьезы, связанные с этим модулем из системы TS.
TypeChecker имеет размер 2,67 МБ и находится по этому адресу, и он способен на некоторые сенсационные вещи. Лучшие изображения, которые могут объяснить, что он может делать, следующие
Слои
Изображение ниже представляет собой обзор того, как TypeScript работает под кулисами, и очень важно знать, что они делают, прежде чем генерировать JS-код, который считывается браузером.
Эти изображения взяты из репозитория microsoft
Gists
Те, кто следит за мной в twitter, знают, что я делаю много кода на уровне типов. Обычно они находятся на github gists здесь Сегодня я собираюсь проанализировать один относительно простой, но очень красивый парсер HTML, который я реализовал, и если бы я делал его на уровне обычного кода, он, возможно, выглядел бы очень похоже.
Ниже я прокомментирую, как создать код в TypeLevel.
Кажется, что кода очень много, но если немного успокоиться, то можно понять, что делает этот код?
Text extends `${infer L}${infer R}`
Возьмите Text и разделите его на две части L и R, в первой итерации слова типа Charizard L будет C, а R — harizard, и так далее, это работает и в массивах.
Для расширения таким способом нужны символы ? и :, если значение истинно, то поток будет продолжен, если нет, то это означает, что он завершил объект, который вы пытаетесь разделить. У вас должен быть запасной вариант, если это произойдет.
Расширяет ?
Слово extends в системе типов используется не только для создания переменных, но и как синоним проверки равенства. В приведенном выше коде мы используем его именно так:
L extends '<' // Em ts normal poderia ser L === '<' ? ... : ... ou apenas if (L === '<') {...}
Пока мы видели некоторые вещи, система типов ориентирована на чистые функции, т.е. я работаю только с тем, что получаю на входе, и никаких побочных эффектов.
Помимо возможности делать if’ы, создавать переменные, нам нужны циклы, чтобы иметь возможность создавать что-либо в языке.
У нас есть это, и это тот момент, когда мне нравится думать, что мы, как ленивые программисты, обычно забываем об этом.
Рекурсия
Самый простой способ итерации — это рекурсия. В системах типов мы можем добиться этого, вызывая тип снова, а не возвращая его. В приведенном выше примере я делал это каждый раз и создавал побочные эффекты как раз вовремя, чтобы снова вызвать рекурсию.
// Você passa texto simples aqui e ele irá só parar quando ver outro <
type ContentParser
<Text extends string, Result extends string = ''> =
Text extends `${infer L}${infer R}`
? L extends '<'
? Result
: ContentParser<R, `${Result}${L}` >
: never
Вопрос в том, как он создает этот текст, который он возвращает, каждый раз, когда я итерирую через тип, я конкатенирую текст Result, пока я не получу момент, когда ему больше ничего не нужно, и я возвращаю его.
Я могу получить тот же результат с помощью приведенной ниже функции:
type ContentParser
<Text extends string, Result extends string = ''> =
Text extends `${infer L}${infer R}`
? L extends '<'
? Result
: ContentParser<R, `${Result}${L}` >
: never
const biggerThanRemover = (text: string, res: string = ''): string => {
const [l, ...r] = text.split('');
if (l === '<') {
return res;
}
return biggerThanRemover(r.join(''), `${res}${l}`);
}
const charizard: ContentParser<'charizard<'> = biggerThanRemover('charizard<') as 'charizard'
console.log(charizard) // charizard
Да, этот простой код — то, что нужно для создания цикла, и я нахожу его гораздо более элегантным, чем классический цикл for, а самое лучшее — это то, что он является чистой функцией, то есть очень прост для тестирования и использования.
Делает ли это меня лучшим программистом?
Да, наличие большего количества оружия в вашем арсенале сделает вас более способным справляться с неблагоприятными ситуациями, и вы сможете сказать, что стоит или не стоит делать в определенных сценариях.
Уметь делать цикл с рекурсией — это то, что я говорю сегодня, что я узнал с полной уверенностью после того, как много играл с системой типов, и без этого времени это было бы невозможно.
Изучение чего-либо даже ради удовольствия и увлечения поможет вам научиться чему-то и достичь определенных пределов, которые раньше были недостижимы.
Заключение
Наконец, я оставлю практический пример, который я узнал, чтобы ваши коллеги devs имели лучший devXP (известный devUX) является существенным, с пользовательскими сообщениями об ошибках в соответствии с типами ошибок может быть что-то, что поможет вашим коллегам быть более продуктивными.
Ниже приведен код, который я считаю чистейшим золотом, которое вы можете найти в интернете, ссылка из поста, который я нашел:
Помимо того, что он дает подсветку синтаксиса ошибки, вы можете аргументировать, что не так, более пояснительным текстом, чем просто x не присваивается типу y.
Наслаждайтесь и используйте его с пользой 😀
Ссылки
Я хотел бы добавить несколько ссылок, которые делают его полезным или приятным для понимания:
- Мэтт Покок
- Структурная типизация
- TypeGame