JavaScript
TypeScript

型定義ベースのアサーションライブラリ types-assert を書いた

More than 1 year has passed since last update.

TypeScriptの型定義ファイル(interface)を活用した、型アサーションライブラリです。

types-assert

使い方

$ npm i types-assert -D

TypeScriptの型定義ファイルを用意する。

type.ts
interface Interface1 {
  stringProp: string;
  numProp: number;
}

in node.js

使うのは、compile()assert()のみ。compile()でtsファイルをロードし、assert()で型チェックする。

app.js
const compile = require('types-assert/compiler').compile;
const assert = require('types-assert/assert').assert;

// tsファイルをtypes-assertのオブジェクトに変換
const type = compile('type.ts');

const obj1 = {
  stringProp: "hoge",
  numProp: 2
};

// 型が正しい場合はスルー
assert(obj1, type.Interface1);

const obj2 = {
  stringProp: "hoge",
  numProp: "2"
};

// 型がおかしいのでError
assert(obj2, type.Interface1);

in browser

Webpack用のtypes-assert-loaderを作った。

$ npm i types-assert-loader -D

Webpackにloaderを定義。

webpack.conf.js
{
  module: {
    loaders: [
      {
        test: /\.ts$/,
        loader: 'types-assert-loader'
      }
    ]
  }
};

.tsファイルをimportすると、Loaderがコンパイルしたオブジェクトを返してくれるので、それでassertする。

index.js
import { assert } from 'types-assert/assert';

import { Interface1 } from './type.ts';

console.log(Interface1);

const obj1 = {
  stringProp: "hoge",
  numProp: "2"
};

// Error!
assert(obj1, Interface1);

何故作ったか

もちろんテスト用のアサーションとしても使えるけど、どちらかというと開発用途を想定している。プロダクションのときはunassertとかで削れるはず。たぶん。

TypeScript好きだけど、辛い

TypeScriptは良い。Objectの型定義を作っておけば、REST APIのレスポンスや、ORMから返ってくるオブジェクトの使いが楽になる。

でも、全てをTypeScriptで書くのは辛い。例えば、バックエンドはnode.jsでTypeScriptを使っているけど、フロントはプレーンなJS、ということがある(コードのライフサイクルや色々な問題で)。そうなると、バックエンド用に作った型定義ファイルがもったいない。

なので、assertという関数ひとつでObjectを再帰的に型チェックできたら良いなと思って作った。

プレーンなObjectを使うことが増えた

Redux(flux)の流行もあり、フロントエンドで標準の型(string、Object、...)だけで構成されたObjectを使う機会が増えた。気がする。

でもReactのpropTypeは嫌い。

なので、assertという関数ひとつでObjectを再帰的に型チェックできたら良いなと思って作った。

TypeScriptの型定義を使う理由

既存のプラットフォームに乗っかる方が楽。また、仮にTypeScriptを使わなくても、型定義ファイルは仕様書としての役割も果たすので、作っておいて損はない。

ただ、今回はTypeScript用に作ったけど、別にコンパイル元のファイルは言語を問わない。JavaやGoのInterfaceからでも(ASTがあれば)同じことは実現できるはず。

まとめ

ふと思いついて作ってみたものなので、どれだけ実用的かはこれから。
あと、コードは適当だしサポートしてない部分もある。Arrayのgenericsも、独自型(interface)の定義もできていない(サポートするかは置いといて)。

誰かが使ってくれるようなら直していく。