← Усі задачіTypeScript · Senior

Branded types: UserId і OrderId

У коді є ідентифікатори користувачів (u_ann) і замовлень (o_42) - обидва рядки, тож їх легко переплутати в аргументах. Зробіть UserId і OrderId різними типами: звичайний рядок і чужий ідентифікатор не мають присвоюватися, але сам UserId має лишатися рядком (toUpperCase, присвоєння в string).

Функції userId(value) і orderId(value) перевіряють формат (u_ і літери, цифри або _; o_ і цифри), кидають помилку Invalid UserId / Invalid OrderId і повертають значення з потрібним типом.

Тести (7)

Тести типів перевіряє компілятор TypeScript у режимі strict. Expect<Equal<A, B>> проходить, коли типи збігаються точно, а // @ts-expect-error - коли наступний рядок не компілюється. Перший запуск завантажує компілятор, тож триває кілька секунд.

  1. типи
    // @ts-expect-error - a plain string is not a UserId
    const id: UserId = 'u_ann';
  2. типи
    const u = userId('u_ann');
    // @ts-expect-error - a UserId is not an OrderId
    const o: OrderId = u;
  3. типи
    const u = userId('u_ann');
    const s: string = u;
    const upper = u.toUpperCase();
  4. типи
    type _ = Expect<Equal<ReturnType<typeof orderId>, OrderId>>;
  5. expect(userId('u_ann')).toBe('u_ann');
    expect(orderId('o_42')).toBe('o_42');
  6. expect(() => userId('ann')).toThrow('Invalid UserId');
  7. expect(() => orderId('o_abc')).toThrow('Invalid OrderId');
    expect(() => orderId('u_1')).toThrow('Invalid OrderId');