4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

かゆい所に手が届く TypeScript の 型ユーティリティ・ライブラリ 【ts-toolbelt の紹介】

Last updated at Posted at 2021-05-22

image.png
※ 画像は 公式リポジトリ より引用

はじめに

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) を参照ください。

  1. README/About より 2 3 4

  2. 他にもあればコメントて教えていただければ幸いです。

4
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
4
3

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?