Branded types: UserId і OrderId
У коді є ідентифікатори користувачів (u_ann) і замовлень (o_42) - обидва рядки, тож їх легко переплутати в аргументах. Зробіть UserId і OrderId різними типами: звичайний рядок і чужий ідентифікатор не мають присвоюватися, але сам UserId має лишатися рядком (toUpperCase, присвоєння в string).
Функції userId(value) і orderId(value) перевіряють формат (u_ і літери, цифри або _; o_ і цифри), кидають помилку Invalid UserId / Invalid OrderId і повертають значення з потрібним типом.
Ctrl+Enter - запустити тести. Tab - відступ; щоб вийти з редактора клавіатурою, натисніть Esc, а потім Tab. Код зберігається в цьому браузері.
Тести (7)
Тести типів перевіряє компілятор TypeScript у режимі strict. Expect<Equal<A, B>> проходить, коли типи збігаються точно, а // @ts-expect-error - коли наступний рядок не компілюється. Перший запуск завантажує компілятор, тож триває кілька секунд.
- типи
// @ts-expect-error - a plain string is not a UserId const id: UserId = 'u_ann';
- типи
const u = userId('u_ann'); // @ts-expect-error - a UserId is not an OrderId const o: OrderId = u;
- типи
const u = userId('u_ann'); const s: string = u; const upper = u.toUpperCase();
- типи
type _ = Expect<Equal<ReturnType<typeof orderId>, OrderId>>;
expect(userId('u_ann')).toBe('u_ann'); expect(orderId('o_42')).toBe('o_42');
expect(() => userId('ann')).toThrow('Invalid UserId');
expect(() => orderId('o_abc')).toThrow('Invalid OrderId'); expect(() => orderId('u_1')).toThrow('Invalid OrderId');