<aside> 💡

チャプター完了時点のソースコード

https://github.com/craftgear/api_handson/tree/ch03

</aside>

zod https://zod.dev/

  1. zodをインストール

    npm i zod
    
  2. /src/todo/domain.ts を作成、zodを使ってバリデーションスキーマと型を定義

    import { z } from 'zod';
    
    export const TodoSchema = z.object({
      id: z.number().brand('TodoId'),
      title: z.string(),
      done: z.coerce.boolean().default(false),
      doneAt: z.coerce.date().nullish(),
    });
    
    export type Todo = z.infer<typeof TodoSchema>;
    export type TodoId = Todo['id'];
    
  3. JSONのパース関数を追加

    export const parseTodo = (data: unknown): Todo => TodoSchema.parse(data);
    export const parseTodoId = (id: number): TodoId => TodoSchema.shape.id.parse(id);
    
  4. 新しく追加するTodoには id がないので、 NewTodo という型を追加する。

    export type NewTodo = Omit<Todo, 'id'>;
    export const parseNewTodo = (data: unknown): NewTodo => TodoSchema.omit({ id: true }).parse(data);
    
  5. vitestをインストール

npm i -D vitest
  1. テスト作成 /src/todo/domain.spec.ts

    import { describe, it, expect, expectTypeOf } from 'vitest';
    import {
      parseTodo,
      parseTodoId,
      parseNewTodo,
      Todo,
      TodoId,
      NewTodo,
    } from './domain';
    
    describe('parseTodo', () => {
      it('parse a valid todo', () => {
        const result = parseTodo({ id: 1, title: "Buy milk" });
        expect(result).toEqual({
          id: 1,
          title: "Buy milk",
          done: false,
        });
        expectTypeOf(result).toEqualTypeOf<Todo>();
        const now = new Date();
        expect(parseTodo({ id: 1, title: 'Buy milk done', done: true, doneAt: now })).toEqual({
          id: 1,
          title: 'Buy milk done',
          done: true,
          doneAt: now,
        });
      });
    });
    
    describe('parseTodoId', () => {
      it('parse a valid todo id', () => {
        const todoId = parseTodoId(1);
        expectTypeOf(todoId).toEqualTypeOf<TodoId>();
      });
    });
    
    describe('parseNewTodo', () => {
       it('parse a valid new todo', () => {
         const result = parseNewTodo({ title: "Buy milk" });
         expect(result).toEqual({
           title: "Buy milk",
           done: false,
         });
         expectTypeOf(result).toEqualTypeOf<NewTodo>();
       });
     });
    
  2. package.jsontest コマンドを追加

  3. テスト実行

    npm test