はじめに

Deno公式が公開しているライブラリ @std/testingで、Deno環境では型レベルプログラミングのユニットテストを書くことができると知ったので方法を共有します。

手前味噌ながら型レベルプログラミングについては別の拙稿にて紹介していますのでご参照ください。

https://qiita.com/umiushi_1/items/4aa25df3343c5b2be62d

環境構築

Denoを利用できるセットアップが必要です。

https://docs.deno.com/runtime/manual/getting_started/installation

上記のページに従い、インストール等を行ってください。

作業ディレクトリを切る

# 各自の所定の作業ディレクトリから
mkdir deno-type-test
cd deno-type-test
deno init
✅ Project initialized

Run these commands to get started

  # Run the program
  deno run main.ts

  # Run the program and watch for file changes
  deno task dev

  # Run the tests
  deno test

上記のように表示されればOKです。

ちなみにフォルダ内は以下のようになっています。

.
├── deno.json
├── main.ts
└── main_test.ts

実際に型レベルプログラミングを行う

/**
 * 型引数に配列を渡したときに、渡した要素の型を返す型レベルプログラミング.
 */
export type ArrayOf<T extends unknown[]> = T extends (infer E)[] ? E : never;

これに対するテストを書いてみましょう。まず、テスト用にパッケージを追加します。

@std/testingJSRで公開されていますので、deno addコマンドで追加することができます。

# deno-type-testにいる状態で
deno add @std/testing

以下のように追加された旨コンソール表示されます。

Add @std/testing - jsr:@std/testing@^0.225.3

テストを書く

では実際にテストを書きます。 @std/testing/typesAssertTrueIsExactを利用します。 AssertTrueは型引数の型がtrueかを判定します。 IsExactは二つの型引数を取り、それらが一致するかを判定します。

参考)

https://jsr.io/@std/testing@0.225.3/doc/types/~/AssertTrue

https://jsr.io/@std/testing@0.225.3/doc/types/~/IsExact

import type { AssertTrue, IsExact } from "@std/testing/types";
import { ArrayOf } from "./main.ts";

Deno.test("ArrayOf", async (t) => {
  await t.step("Tがnumber[]のとき、型がnumberとなること", () => {
    type Expected = number;
    type Actual = ArrayOf<number[]>;
    type _ = AssertTrue<IsExact<Expected, Actual>>;
  });

  await t.step(
    "Tが(string | number)[]のとき、型がstring | numberとなること",
    () => {
      type Expected = string | number;
      type Actual = ArrayOf<(string | number)[]>;
      type _ = AssertTrue<IsExact<Expected, Actual>>;
    }
  );

  await t.step("Tが ('a' | 1)[]のとき、型が 'a'|1となること", () => {
    type Expected = "a" | 1;
    type Actual = ArrayOf<("a" | 1)[]>;
    type _ = AssertTrue<IsExact<Expected, Actual>>;
  });
});

テストを実行する

# 所定のディレクトリ上で
deno test
Check file:///path/to/deno-type-test/main_test.ts
running 1 test from ./main_test.ts
ArrayOf ...
  Tがnumber[]のとき、型がnumberとなること ... ok (1ms)
  Tが(string | number)[]のとき、型がstring | numberとなること ... ok (0ms)
  Tが ('a' | 1)[]のとき、型が 'a'|1となること ... ok (0ms)
ArrayOf ... ok (2ms)

ok | 1 passed (3 steps) | 0 failed (3ms)

以上です。 ただし、カバレッジは取れないようです。

おわりに

今回はDeno環境で型レベルプログラミングの単体テストを書く方法について紹介しました。 上記の方法の場合はDeno環境に限定されますが、IsExactの実装は公開されていますし、LICENSEもMITとなっていますので、同様の型定義を利用してNode環境などでも型レベルプログラミングの単体テストを実施することが可能だと思います。

https://jsr.io/@std/testing/0.225.3/types.ts#L162

ちなみにJSRは(ESM前提なら)Node環境などにも依存関係として追加できますが、このライブラリはDeno環境での利用前提のためうまく動きません。

記事一覧に戻る