Декабрь в офисе не проходит без традиции тайного Санты. Мой вишлист остался пустым, но подарок, который я получила, удивил своей точностью. А вместе с ним пришло загадочное послание. Как новичку в компании, мне было трудно с первого взгляда угадать отправителя, поэтому я решила использовать TypeScript, чтобы найти своего Санту.
Подарок и сообщение ????
Вместе с подарком я получила тайное послание, которое стало отправной точкой типизации.
Используя подсказки из послания, я определила типы, соответствующие каждому ключевому качеству Санты.
type HasSenseOfHumor = { hasSenseOfHumor: true };
type KnowsMyTaste = { knowsMyTaste: true };
type CanFindUniqueGifts = { canFindUniqueGifts: true };
type LeavesMysteriousMessages = { leavesMysteriousMessages: true };
type LovesCats = { lovesCats: true };
type UsesTripleEmoji = { usesTripleEmoji: true };
Изучение данных ????
В треде нашего корпоративного Slack я нашла имена всех участников и приуныла: никаких общих закономерностей, каждого можно описать только уникальным набором свойств. Конфиденциальность не позволяет мне раскрыть реальные имена, поэтому в роли примеров выступят Bob и Alice — условные Санты с характерными атрибутами.
type ParticipantA = {
name: 'Alice';
hasSenseOfHumor: true;
knowsMyTaste: true;
canFindUniqueGifts: true;
leavesMysteriousMessages: false;
usesTripleEmoji: false;
};
type ParticipantB = {
name: 'Bob';
hasSenseOfHumor: true;
knowsMyTaste: true;
canFindUniqueGifts: true;
leavesMysteriousMessages: true;
lovesCats: true;
usesTripleEmoji: true;
};
Чтобы создать универсальный тип для всего списка, мне пришлось вручную назначить типы, соответствующие индивидуальности каждого участника, допуская, что у них могут быть и другие, ещё не известные мне характеристики.
type AllParticipants = ParticipantA | ParticipantB;
Фильтрация кандидатов ????
Пришло время сузить круг поисков, применяя строгую типизацию. Отстраняя субъективные атрибуты, я сосредоточилась на четко определённых качествах, поддающихся логической проверке.
type FilteredParticipants = Extract<
AllParticipants,
HasSenseOfHumor & LeavesMysteriousMessages & UsesTripleEmoji
>;
Моей задачей было убедиться, что найдётся только один человек, который соответствует всем критериям. Поэтому я добавила условный тип, который исключал случай множественного совпадения.
type IsSingle<T, All = T> = T extends any
? Exclude<All, T> extends never
? T
: never
: never;
Если бы критериям соответствовало большее количество людей, это бы означало, что мне нужно пересмотреть эти критерии или учесть дополнительные факторы.
Разгадка ????
Силой типов и условных выражений я ограничила выбор до одного человека, который мог быть моим Тайным Сантой.
type SingleSecretSanta = IsSingle<FilteredParticipants>
Осталось только навести курсор на type SecretSanta
и позволить TypeScript подсказать мне, кто же скрывается за этой загадкой.
type SecretSanta = SingleSecretSanta extends never
? 'No single match found'
: SingleSecretSanta;
Узнать итог моего поиска можно здесь — код доступен в TypeScript Playground.
AstorS1
Тоже хочу узнать своего тайного Санту. Подарок достаточно дорогой (в 6 раз выше обсуждённого комфортного лимита) , но очень в тему! И мне бы хотелось приватно компенсировать часть затрат.
Но мне проще, к подарку было приложено рукописное письмо. Не знаю, сам ли Санта его писал или его помощники. Правда дело осложняется тем, что мы в разных локация, 250+ участников.