Qiita Teams that are logged in
You are not logged in to any team

Log in to Qiita Team
Community
OrganizationEventAdvent CalendarQiitadon (β)
Service
Qiita JobsQiita ZineQiita Blog
21
Help us understand the problem. What are the problem?

More than 5 years have passed since last update.

posted at

updated at

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

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)の定義もできていない(サポートするかは置いといて)。

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

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
21
Help us understand the problem. What are the problem?