[Разработка веб-сайтов, Программирование, TypeScript] ТайпСкрип: Ох уж эта весёлая система типов
Автор
Сообщение
news_bot ®
Стаж: 6 лет 9 месяцев
Сообщений: 27286
Здравствуйте, меня зовут Дмитрий Карловский и недавно я, вместе с Артуром Мукминовым, проводил воркшоп, где показывал как разрабатывать сложные типофункции через тестирование. Это 2 часа сурового программирования на типах. Так что в качестве тизера, ловите разбор курьёзов тайпскриптовой системы типов.
Отношения — это сложно
Проверить является ли один тип подтипом другого очень просто, используя типотернарник:
type IsAExtendsB = A extends B ? true : false
На воркшопе мы разработали типофункцию Classify, принимающую 2 типа и возвращающую одно из 4 возможных значений:
- [ A, '<:', B ] — A является строгим подтипом B.
- [ A, ':>', B ] — B является строгим подтипом A.
- [ A, '==', B ] — Оба типа являются подтипами друг друга (но не обязательно являются одинаковыми типами).
- [ A, '!=', B ] — Ни один тип не является подтипом другого.
Кроме того, мы запилили типофункции Equal и Assert, позволяющие сравнивать типы на равенство, независимо от того, считает ли компилятор два разных типа подтипами друг друга или нет. Assert при этом ещё и валит проверку типов, если типы вдруг не совпали.
Всё есть объекты! Но это не точно..
Ну и первый же прикол — Object и object — это определённо разные типы, ибо примитивные типы являются подтипами первого, но не второго:
type boolean_is_Object = Assert<
boolean extends Object ? true : false,
true
>
type boolean_is_not_object = Assert<
boolean extends object ? true : false,
false
>
Однако, если мы сравним их, то выяснится, что они являются подтипами друг друга:
type Object_vs_object = Assert<
Classify< Object, object >,
[ Object, '==', object ]
>
То есть отношение подтипизации в тайпскрипте не является транзитивным: если один тип (например, boolean) является подтипом другого (например, Object), а другой — третьего (например, object), то первый вовсе не обязательно является подтипом третьего — это надо проверять отдельно.
На диаграмме, все объектные типы раскрашены в голубой цвет. Они являются подтипами как Object, так и object.
Разные типы перечислений типов
Раз уж мы заговорили про булевый тип, то нельзя не упомянуть, что он — ничто иное, как кроткий алиас для объединения пары литеральных типов:
type boolean_is_true_or_false = Assert<
boolean,
true | false
>
С числовыми перечислениями всё в принципе аналогично:
enum FL4 { Absurd, False, True, Unknown }
type FL4_is_union = Assert<
FL4,
| FL4.Absurd | FL4.False | FL4.True | FL4.Unknown
>
И состоят они вроде бы из чисел (даже не литералов):
type Absurd_is_number = Assert<
Classify< FL4.Absurd, number >,
[ FL4.Absurd, '==', number ]
>
Но тут тайпскрипту внезапно сносит крышу:
type Absurd_is_never_wtf = Assert<
Classify< FL4.Absurd, 0 >,
[ never, '<:', 0 ]
>
Эй, тайпскрипт, ты куда первый тип потерял? Верни, где взял!
type One_is_never_wtf = Assert<
Classify< FL4.Absurd, 1 >,
[ FL4.Absurd, ':>', never ]
>
Вот, спасибо, совсем другое дело!
По всей видимости связано это с тем, что значения перечислений — это не не простые литералы, а уникальные:
enum FL3 { Absurd, False, True }
type Absurd_is_not_Absurd = Assert<
Equal< FL3.Absurd, FL4.Absurd > | false,
false
>
Ну да ладно, у нас ещё остались не разобранными строковые перечисления. Может показаться, что ведут они себя как и числовые, однако, внезапно:
enum HappyDebugging {
False = "True",
True = "False",
}
type True_extends_string = Assert<
Classify< HappyDebugging.True, string >,
[ HappyDebugging.True, '<:', string ]
>
Получается, что number является подтипом числового перечисления, а вот string подтипом строкового уже нет.
Призраки прошлого
В Тайпскрипте есть пара специальных типов, которые находятся на противоположных концах иерархии:
- never представляет из себя пустое множество значений. То есть он является подтипом любого типа, и никакой другой тип не может быть его подтипом.
- unknown же — это множество всех возможных значений. То есть это объединение вообще всех типов в один. Поэтому любой тип является подтипом unknown.
Но что это маячит рядом с ними? Да это же any! С одной стороны он полностью взаимозаменяем с unknown:
type unknown_is_any = Assert<
unknown,
any
>
Но с другой же, он как кот Шрёдингера является подтипом never (и как следствие, любого другого типа до unknown) и не является таковым одновременно:
type any_maybe_extends_never = Assert<
any extends never ? true : false,
true | false
>
Короче, any пробивает дно во всех возможных смыслах. Тяжела участь тех, кто столкнётся с ним лицом к лицу...
Весь код из статьи.
Счастливой отладки, ребята!
===========
Источник:
habr.com
===========
Похожие новости:
- [Разработка веб-сайтов, JavaScript] JavaScript исполняется 25 лет: краткая история языка и скидка 50% на WebStorm
- [Программирование, Разработка под iOS, Objective C, Swift] Модуляризация iOS-приложения: зачем и как мы разбиваем Badoo на модули
- [Программирование, C++] Небольшие, но важные функции (перевод)
- [Программирование, Управление разработкой, Управление персоналом, Карьера в IT-индустрии] О плюсах парного программирования
- [Программирование, CRM-системы] Интегрируем web-телефон в свою систему
- [Разработка веб-сайтов, JavaScript] Web Components и IoC
- [Python, Программирование] Как работает память в Python
- [Разработка веб-сайтов, Системное администрирование, DevOps, Микросервисы] End User Monitoring на примере Instana
- [Высокая производительность, JavaScript, Программирование, TypeScript] Производительность TypeScript (перевод)
- [Программирование, Java, Тестирование веб-сервисов, Тестирование мобильных приложений] Рекомендации по использованию IF в Java (перевод)
Теги для поиска: #_razrabotka_vebsajtov (Разработка веб-сайтов), #_programmirovanie (Программирование), #_typescript, #_typescript, #_type_systems, #_types, #_razrabotka_vebsajtov (
Разработка веб-сайтов
), #_programmirovanie (
Программирование
), #_typescript
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 14:43
Часовой пояс: UTC + 5
Автор | Сообщение |
---|---|
news_bot ®
Стаж: 6 лет 9 месяцев |
|
Здравствуйте, меня зовут Дмитрий Карловский и недавно я, вместе с Артуром Мукминовым, проводил воркшоп, где показывал как разрабатывать сложные типофункции через тестирование. Это 2 часа сурового программирования на типах. Так что в качестве тизера, ловите разбор курьёзов тайпскриптовой системы типов. Отношения — это сложно Проверить является ли один тип подтипом другого очень просто, используя типотернарник: type IsAExtendsB = A extends B ? true : false
На воркшопе мы разработали типофункцию Classify, принимающую 2 типа и возвращающую одно из 4 возможных значений:
Кроме того, мы запилили типофункции Equal и Assert, позволяющие сравнивать типы на равенство, независимо от того, считает ли компилятор два разных типа подтипами друг друга или нет. Assert при этом ещё и валит проверку типов, если типы вдруг не совпали. Всё есть объекты! Но это не точно.. Ну и первый же прикол — Object и object — это определённо разные типы, ибо примитивные типы являются подтипами первого, но не второго: type boolean_is_Object = Assert<
boolean extends Object ? true : false, true > type boolean_is_not_object = Assert< boolean extends object ? true : false, false > Однако, если мы сравним их, то выяснится, что они являются подтипами друг друга: type Object_vs_object = Assert<
Classify< Object, object >, [ Object, '==', object ] > То есть отношение подтипизации в тайпскрипте не является транзитивным: если один тип (например, boolean) является подтипом другого (например, Object), а другой — третьего (например, object), то первый вовсе не обязательно является подтипом третьего — это надо проверять отдельно. На диаграмме, все объектные типы раскрашены в голубой цвет. Они являются подтипами как Object, так и object. Разные типы перечислений типов Раз уж мы заговорили про булевый тип, то нельзя не упомянуть, что он — ничто иное, как кроткий алиас для объединения пары литеральных типов: type boolean_is_true_or_false = Assert<
boolean, true | false > С числовыми перечислениями всё в принципе аналогично: enum FL4 { Absurd, False, True, Unknown }
type FL4_is_union = Assert< FL4, | FL4.Absurd | FL4.False | FL4.True | FL4.Unknown > И состоят они вроде бы из чисел (даже не литералов): type Absurd_is_number = Assert<
Classify< FL4.Absurd, number >, [ FL4.Absurd, '==', number ] > Но тут тайпскрипту внезапно сносит крышу: type Absurd_is_never_wtf = Assert<
Classify< FL4.Absurd, 0 >, [ never, '<:', 0 ] > Эй, тайпскрипт, ты куда первый тип потерял? Верни, где взял! type One_is_never_wtf = Assert<
Classify< FL4.Absurd, 1 >, [ FL4.Absurd, ':>', never ] > Вот, спасибо, совсем другое дело! По всей видимости связано это с тем, что значения перечислений — это не не простые литералы, а уникальные: enum FL3 { Absurd, False, True }
type Absurd_is_not_Absurd = Assert< Equal< FL3.Absurd, FL4.Absurd > | false, false > Ну да ладно, у нас ещё остались не разобранными строковые перечисления. Может показаться, что ведут они себя как и числовые, однако, внезапно: enum HappyDebugging {
False = "True", True = "False", } type True_extends_string = Assert< Classify< HappyDebugging.True, string >, [ HappyDebugging.True, '<:', string ] > Получается, что number является подтипом числового перечисления, а вот string подтипом строкового уже нет. Призраки прошлого В Тайпскрипте есть пара специальных типов, которые находятся на противоположных концах иерархии:
Но что это маячит рядом с ними? Да это же any! С одной стороны он полностью взаимозаменяем с unknown: type unknown_is_any = Assert<
unknown, any > Но с другой же, он как кот Шрёдингера является подтипом never (и как следствие, любого другого типа до unknown) и не является таковым одновременно: type any_maybe_extends_never = Assert<
any extends never ? true : false, true | false > Короче, any пробивает дно во всех возможных смыслах. Тяжела участь тех, кто столкнётся с ним лицом к лицу... Весь код из статьи. Счастливой отладки, ребята! =========== Источник: habr.com =========== Похожие новости:
Разработка веб-сайтов ), #_programmirovanie ( Программирование ), #_typescript |
|
Вы не можете начинать темы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Вы не можете отвечать на сообщения
Вы не можете редактировать свои сообщения
Вы не можете удалять свои сообщения
Вы не можете голосовать в опросах
Вы не можете прикреплять файлы к сообщениям
Вы не можете скачивать файлы
Текущее время: 22-Ноя 14:43
Часовой пояс: UTC + 5