Edited at

型定義ベースのアサーションライブラリ 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)の定義もできていない(サポートするかは置いといて)。

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