Absolute
Завдання
Реалізуйте тип Absolute
. Він має приймати string
, number
або bigint
.
Результатом повинно бути додатне число у вигляді рядка.
Наприклад:
type Test = -100;
type Result = Absolute<Test>; // expected to be "100"
Розв’язок
Найлегший спосіб отримати модуль числа - це конвертувати число в рядок й прибрати знак “-“. Я не жартую, в буквальному сенсі прибрати “-“ з рядка.
Почнемо з перевірки чи є знак “-“ на початку рядка. Якщо так, то виводимо все що залишилося, використовуючи умовні типи. В інакшому випадку, у нас додатне число, тому повертаємо його без змін:
type Absolute<T extends number | string | bigint> = T extends `-${infer N}`
? N
: T;
Таким чином, якщо вкажемо T = “-50”
, це відповідатиме нашому шаблону “-<N>”
де N
буде "50"
, й ми його повернемо.
Та ми бачимо, що деякі з тестів все ще не проходять. Це тому, що ми не завжди повертаємо рядки. Наприклад, якщо передати додатне число, воно не збіжиться з рядком в умовному типі й повернеться число замість рядка.
Виправимо це, загорнувши тип T
в рядковий тип-літерал, перед тим, як його
повертати.
type Absolute<T extends number | string | bigint> = T extends `-${infer N}`
? N
: `${T}`;
Все ще не проходять тести… Ми не опрацьовуємо випадок, коли T
це від’ємне
число. Число знову не збігається з нашою умовою, виведення не спрацьовує й ми
повертаємо від’ємне число, тільки в рядку. Щоб подолати це, загорнемо число в
рядковий тип-літерал на початку:
type Absolute<T extends number | string | bigint> = `${T}` extends `-${infer N}`
? N
: `${T}`;
В результаті, ми отримали тип, який приймає number
, string
або bigint
і
конвертує їх в рядок. Потім він виводить частину рядка без знаку “-“, або
повертає його без змін.
Коментарі