9
9

More than 3 years have passed since last update.

単一リポジトリ内の複数のpackageで共通の型を使い、さらに型をpackage化

Last updated at Posted at 2019-12-27

概要

小規模のサーバーサイド・フロントエンドのように、
マルチパッケージを含む構成のリポジトリにおいて・・・

root
├── functions
│   └── package.json    // サーバーサイドの package
└── hosting
    └── package.json    // フロントエンドの package

以下を満たすためのメモです。

  • functions, hosting から単一の型定義を使う
  • root-types package として、型を export する
    • ここでexportした型を、外部のプロジェクトからも使えるようにする

最終形態

上記の条件を満たすリポジトリの最終形です

root
├── package.json  // root-types package
├── types
|   ├── dist      // root-types としての配布物
|   ├── src       // root-types の実装
|   |   ├── index.ts    // root-types で export する名前空間の定義
|   |   ├── modules.ts  // 型をまとめて簡潔に export するためのクッション
|   |   └── impl        // 型の実装
|   |        ├── hoge-types.ts
|   |        └── piyo-types.ts
|   └── tsconfig.json
|
├── functions
│   └── package.json    // サーバーサイドの package
└── hosting
    └── package.json    // フロントエンドの package

root-types package の作成

package.json

types/dist を配布物とします。

package.json
{
  "name": "root-types",
  "main": "types/dist/index.js",
  "files": [ "types/dist" ],
  "scripts": {
    "build": "npx tsc --project types/tsconfig.json",
  },
  "devDependencies": {
    "typescript": "^3.7.4"
  }
}

types/tsconfig.json

types/dist/ に型定義を出力するように定義します。

types/tsconfig.json
{
  "compilerOptions": {
    "module": "commonjs",
    "moduleResolution": "node",
    "noImplicitReturns": true,
    "noUnusedLocals": true,
    "outDir": "dist",
    "sourceMap": true,
    "strict": true,
    "target": "es2017",
    "esModuleInterop": true,
    "allowSyntheticDefaultImports": true,
    "skipLibCheck": true,
    "declaration": true
  },
  "compileOnSave": true,
  "include": ["src"]
}

types/src/index.ts

modules.ts で export しているすべてを、
Root という名前でくるんでexportしています

types/src/index.ts
import * as Root from "./modules";

export { Root };

types/src/modules.ts

types/src/impl/ 以下の実装をまとめて export するためのクッションです
export 対象のファイルが増えるたび、追記します

types/src/modules.ts
export * from "./impl/hoge-types";
export * from "./impl/piyo-types";

types/src/impl

export したい型の実装です

types/src/impl/hoge-types.ts
export interface Hoge {
  str: string;
}
types/src/impl/piyo-types.ts
export enum Piyo {
  ONE = 1,
  TWO = 2,
  THREE = 3,
}

ビルド

npm run build を実行すると、 types/dist/ 以下に型定義 d.ts を伴って出力されます

内部の package から型を参照

hosting/ のソースから、通常の package と同様に root-types を利用できるようにします
(functions/ 以下も同様です)

以下のように利用できるようになります。

hosting/src/index.ts
import { Root } from 'root-types';

const hoge: Root.Hoge = {str: "hello"};
console.log(hoge, Root.Piyo.ONE);
// {str: "hello"} 1

[方法1] npm link

hosting/ 以下で npm link ../ を実行すると、
hosting/node_modules/ 以下に root-types のシンボリックリンクが生成されます

postinstall に link を記述

このままでは毎回 npm link ../ を実行しなくてはなりません。

そこで、 hosting/package.json に以下の script を追記し、
npm install 後に自動的に実行されるようにします

hosting/package.json
  "scripts": {
    "postinstall": "npm link ../",
  }

[方法2] npm install

こっちのほうが楽かもしれません。
./hostingnpm install ../ を実行するだけです

hosting/package.json
"dependencies": {
    "root-types": "file:..",
}

外部の package から利用する

今回作成した root-types package はほかの private プロジェクトで参照するのみで、
npm に publish したりはしません。
外部のプロジェクトで、 root リポジトリを直接参照して root-types をinstallできました。

npm install git+ssh://git@gitlab.com:YOU/root.git --save

package.json
"dependencies": {
  "root-types": "git+ssh://git@gitlab.com:YOU/root.git",
}

参考
nodejsで自作別リポジトリ(gitlab/github)をモジュール化して利用するには?

まとめ

マルチパッケージのリポジトリで型を共有したり、
型をexportして他のリポジトリで使ったりする機会が増えてきたので書きました。

同一リポジトリ・マルチパッケージでサクッと楽して開発できるだけで、
キレイスッキリな構成ではない気がするので、
大きく育てるプロジェクトではもっと最適なソリューションがないか検討したいですね。

9
9
2

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
9
9