※ 画像は 公式リポジトリ より引用
はじめに
ts-toolbelt を簡単に紹介する記事です。TypeScript が提供する Partial などの Utility Types を強化し、より豊富なラインナップにしたイメージのライブラリです。ts-toolbelt があれば、これまで自作していた型ユーティリティが不要になるかもしれません。
概要
- GitHub Star数: 2.4k(2021/5/22時点)
- 最もテストされた最大の型ライブラリ1
- 200以上のユーティリティをもつ1
- lodash や ramda にあるような関数を型レベルで実装1
- 型を計算、変更、作成する簡単な方法を提供することを使命としている1
Star数は TypeScript の 型ユーティリティ・ライブラリ としては一強状態だと思います。2
利用例
筆者が個人的に使用したことのあるユーティリティの一部を紹介します。
オブジェクトの一部のプロパティのみ省略可能にする
標準ユーティリティの Partial は 全てのプロパティを省略可能にしますが、部分的に省略可能にすることができません。ts-toolbelt の Object.Optional
を使えば部分的省略が可能です。
import { Object } from 'ts-toolbelt';
type User = {
name: string
age: number
};
type optional = Object.Optional<User, 'age'>;
// { name: string; age?: number | undefined; }
Object.Compulsory
を使えば、一部の null 又は undefined なプロパティを必須プロパティにできます。
標準ユーティリティにある機能なら、「一部だけ~したい」という要望はだいたい実現可能と思います。
オブジェクトの一部のプロパティを上書きする
import { Object } from "ts-toolbelt";
type User = {
name: string;
age: number;
};
type stringAge = Object.Overwrite<User, { age: string }>;
// { name: string; age: string; }
ネストされたオブジェクトの特定のプロパティの型を取得する
import { Object } from "ts-toolbelt";
type Nested = {
three: {
two: {
one: "Go!";
};
};
};
type letus = Object.Path<Nested, ['three', 'two', 'one']>;
// type letus = "Go!"
オブジェクトの値の Union を取得する
import { Object } from "ts-toolbelt";
const EraChar2Kanji = {
R: '令和',
H: '平成',
S: '昭和'
} as const
type eraKanji = Object.UnionOf<typeof EraChar2Kanji>;
// type eraKanji = "令和" | "平成" | "昭和"
オブジェクトを反転させる
import { Object } from "ts-toolbelt";
const EraChar2Kanji = {
R: '令和',
H: '平成',
S: '昭和'
} as const
type EraKanji2Char = Object.Invert<typeof EraChar2Kanji>;
/* type EraKanji2Char = {
令和: "R";
平成: "H";
昭和: "S";
}*/
Union から特定の型を選択する
import { Union } from "ts-toolbelt";
type EventInfo =
| {
reason: "clear";
}
| { reason: "delete"; id: string };
type selected = Union.Select<EventInfo, { id: string }>;
type reason = selected["reason"];
// type reason = "delete"
Union の差分を取得する
import { Union } from "ts-toolbelt";
type abc = "a" | "b" | "c";
type adc = "a" | "d" | "c";
type diff = Union.Diff<abc, adc>;
// type diff = "b" | "d"
型レベルのテストをする
import { Union, Test } from "ts-toolbelt";
type abc = "a" | "b" | "c";
type adc = "a" | "d" | "c";
type diff = Union.Diff<abc, adc>;
Test.checks([Test.check<diff, "b" | "d", Test.Pass>()]);
// diff は "b" | "d" であることを確認
// Test.checks は型テスト用であるため、実行されるファイルに記載しないようにします。
// どうしても実行時されるファイルに書きたい場合は Test.checks を無名関数等の中に書けばエラーにはなりません。
// 例: () => Test.checks([Test.check<diff, "b" | "d", Test.Pass>()]);
Test
の使い方については、README の Running tests を参照ください。
その他
他にも、型レベルの足し算やオブジェクトのマージなども可能です。
より豊富なサンプルについては、こちらの READMEからリンクされているデモ(CodeSandbox) を参照ください。