Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Vitestを使った型テストの始め方

 Vitestを使った型テストの始め方

Masaki Koyanagi

September 26, 2023
Tweet

More Decks by Masaki Koyanagi

Other Decks in Programming

Transcript

  1. @mascii_k
    WeJS 42nd @freee
    Vitestを使った
    型テストの始め方

    View Slide

  2. 自己紹介
    ますきー (X:@mascii_k)
    freee K.K. エンジニア / WeJS 運営メンバー
    最近は Go,TypeScript を書いています

    View Slide

  3. テスト環境の準備

    View Slide

  4. テスト環境の準備
    ● Vitestでランタイムのテストができていれば、追加パッ
    ケージのインストールは不要
    ● npm run typecheck で型テストをできるようにする
    ○ package.json に以下を追加
    {
    "scripts": {
    "typecheck": "vitest typecheck"
    }
    }

    View Slide

  5. 型テストを書いてみよう

    View Slide

  6. テスト対象
    ● "user:Alice" のような文字列を key, value にパース
    するような関数を考える
    > parse("user:Alice")
    { key: 'user', value: 'Alice' }
    実行例
    function parse(kv: `${T}:${U}`) {
    const [key, value] = kv.split(":");
    return { key, value } as { key: T; value: U };
    }

    View Slide

  7. function parse(kv: `${T}:${U}`) {
    const [key, value] = kv.split(":");
    return { key, value } as { key: T; value: U };
    }
    テスト対象
    ● "user:Alice" のような文字列を key, value にパース
    するような関数を考える
    関数のジェネリクス
    テンプレートリテラル型
    型アサーション
    配列の
    分割代入
    オブジェクトリテラルの
    省略記法
    オブジェクト型
    黄: JavaScriptの記法
    青: TypeScriptの型に関する記法

    View Slide

  8. テストを書く
    test("parse", () => {
    expect(parse("user:Alice"))
    .toEqual({
    key: "user",
    value: "Alice",
    });
    });
    test("parse", () => {
    expectTypeOf(parse("user:Alice"))
    .toEqualTypeOf<{
    key: "user";
    value: "Alice";
    }>();
    });
    ● *.test.ts に
    ランタイムのテスト
    を記述する
    ● *.test-d.ts に
    型テストを記述する

    View Slide

  9. 型テストの書き味
    ● Vitestを走らせなくても、テスト結果をリアルタイム
    に確認できる
    ○ 慣れればランタイムのテストよりクイックに書けるかも?

    View Slide

  10. 活用例

    View Slide

  11. 活用例1: 複雑な戻り値型の関数
    ● 型テストを導入後、リファクタリングや新機能の追加が
    やりやすくなった
    function toObject(form: T): ToObjectOutput {
    // etc...
    }
    type ToObjectOutput = {
    [K in keyof T as T[K] extends PrivateField | ((...args: any[]) => any) ? never : K]
    : T[K] extends Form
    ? ToObjectOutput
    : T[K] extends FieldWithPreferredType
    ? U2
    : T[K] extends FormsField
    ? ToObjectOutput>[]
    : never;
    };
    vue-yup-form
    https://github.com/mascii/vue-yup-form

    View Slide

  12. 活用例2: Reactコンポーネントのprops
    ● 「あるpropが指定された場合はchildrenを持てない」
    といったテストを *.test-d.tsx で書くことができる
    import { Route } from "react-router-dom";
    test("Route", () => {
    assertType(
    // @ts-expect-error index 指定時は children を持てません




    );
    });

    View Slide

  13. まとめ

    View Slide

  14. まとめ
    ● Vitestが入っている環境なら、簡単に型テストを
    書き始められる
    ● 型テストがあると、型のリファクタリングや機能追
    加をやりやすくなる

    View Slide