[[TypeScript]]の[[npmパッケージ]]を作成するメモ。以下の記事を参考に。 <div class="link-card-v2"> <div class="link-card-v2-site"> <img class="link-card-v2-site-icon" src="https://spin.atomicobject.com/wp-content/uploads/cropped-AO-Favicon-512-32x32.png" /> <span class="link-card-v2-site-name">Atomic Spin</span> </div> <div class="link-card-v2-title"> How to Create an NPM Package in TypeScript from the Ground Up </div> <div class="link-card-v2-content"> Demystify the creation of a TypeScript NPM package by starting from the absolute minimum amount of code and buil ... </div> <img class="link-card-v2-image" src="https://spin.atomicobject.com/wp-content/uploads/Screenshot-2024-11-25-at-1.45.24-PM.png" /> <a href="https://spin.atomicobject.com/npm-package-typescript/"></a> </div> ## まずは[[JavaScript]]で書かれた最小限のモノを 初めはシンプルに本質を理解すべしということだろう。やってみる。 ### ライブラリプロジェクトの作成 ```console mkdir mimizou-libtest cd mimizou-libtest ``` `name`のみを指定した[[package.json]]を作る。publishしなければ`version`は必ずしも必須ではないらしい。[[スコープ (npm)|スコープ]]を指定する。 `mimizou-libtest/package.json` ```json { "name": "@tadashi-aikawa/mimizou-libtest" } ``` そして、`{hello: (name: string): string}`な[[プロパティ (TypeScript)|プロパティ]]をもつ。 `mimizou-libtest/index.js` ```js module.exports = { hello: (name) => "Hello, " + name + "!" }; ``` ### ライブラリ利用プロジェクトの作成 別のディレクトリで`@tadashi-aikawa/mimizou-libtest`を呼び出す[[CLI]]のコードを作成。 ```console cd ../ mkdir mimizou-cli cd mimizou-cli ``` `mimizou-cli/index.js` ```js const { hello } = require('@tadashi-aikawa/mimizou-libtest'); console.log(hello('world')); ``` これだけだと、`@tadashi-aikawa/mimizou-libtest`は[[モジュール (TypeScript)|モジュール]]として認識されない。そこでいつものように[[npm install]]する。違いはパッケージ名ではなくパスを指定するということだ。 ```console npm install ../mimizou-libtest ``` [[package.json]]は未作成だったが、勝手に作成された。 `mimizou-cli/package.json` ```json { "dependencies": { "@tadashi-aikawa/mimizou-lib-test": "file:../mimizou-libtest" } } ``` これで[[IDE]]でも補完が効く。実行すれば期待通り動く。 ```console $ node index.js Hello, world! ``` ## ライブラリ利用プロジェクトの[[TypeScript]]化 ### [[TypeScript]]のインストール `mimizou-cli`のプロジェクトを[[TypeScript]]対応する。 ```console npm i -D typescript ``` ### [[tsconfig.json]]ベースのインストール [[tsconfig.json]]には[[TSConfig bases]]を使う。 ```console npm install -D @tsconfig/node18 ``` `mimizou-cli/tsconfig.json` ```json { "extends": "@tsconfig/node18/tsconfig.json" } ``` ### [[tsconfig.json]]の設定 [[JavaScript]]ファイルは`lib`配下に格納したいので、[[outDir]]と[[include (tsconfig)|include]]を設定する。 `mimizou-cli/tsconfig.json` ```json { "extends": "@tsconfig/node18/tsconfig.json", "include": ["src/**/*"], "compilerOptions": { "lib": ["es2022", "dom"], "outDir": "lib" } } ``` > [!caution] > 参照元のサイトでは[[lib (tsconfig)|lib]]に`dom`が追加されていなかった (注意喚起はされているけど) ### コードの変更 実行側、`mimizou-cli`の`index.js`を`index.ts`に変更し、`src`ディレクトリ配下に移動する。 `mimizou-cli/src/index.ts` ```ts import { hello } from "@tadashi-aikawa/mimizou-lib-test"; console.log(hello("world")); ``` [[package.json]]に`scripts`を追加。`dependencies`の相対パスも調整する。 `mimizou-cli/package.json` ```json { "scripts": { "build": "tsc" }, "dependencies": { "@tadashi-aikawa/mimizou-lib-test": "file:../../mimizou-libtest" }, "devDependencies": { "@tsconfig/node18": "^1.0.1", "typescript": "^4.9.5" } } ``` ビルドするとエラーが出る。 ```console $ npm run build src/index.ts:1:23 - error TS7016: Could not find a declaration file for module '@tadashi-aikawa/mimizou-lib-test'. 'C:/Users/syoum/tmp/npm-sandbox/mimizou-libtest/index.js' implicitly has an 'any' type. 1 import { hello } from "@tadashi-aikawa/mimizou-lib-test"; ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ``` `mimizou-libtest`には型定義がないので、[[TypeScript]]としてはimportできないであろう。 ## ライブラリプロジェクトの[[TypeScript]]化 - エントリポイントは[[package.json]]の`main` - デフォルト値は`index.js` - 型定義は[[package.json]]の`types` ### [[TypeScript]]と[[tsconfig.json]]の準備 [[TypeScript]]と[[tsconfig.json]]のベースをインストール。 ```console npm install -D typescript @tsconfig/node18 ``` [[tsconfig.json]]は`mimizou-cli`をベースに以下の変更を加える。 - [[lib (tsconfig)|lib]]から`dom`を削除 - [[console.log]]は不要なため - [[declaration]]に`true`を指定 - 型定義ファイルを生成するため `mimizou-libtest/tsconfig.json` ```json { "extends": "@tsconfig/node18/tsconfig.json", "include": ["src/**/*"], "compilerOptions": { "outDir": "lib", "declaration": true }, } ``` ### コードの変更 [[JavaScript]]ファイルを[[TypeScript]]ファイルに。 `mimizou-libtest/src/index.ts` ```ts export const hello = (name: string): string => "Hello, " + name + "!"; ``` ### ビルド `mimizou-libtest/package.json` ```json { "name": "@tadashi-aikawa/mimizou-lib-test", "scripts": { "build": "tsc" }, "devDependencies": { "@tsconfig/node18": "^1.0.1", "typescript": "^4.9.5" } } ``` ビルドする。 ```console npm run build ``` 成功すると、`lib`ディレクトリが作成され、`index.d.ts`と`index.js`が生成されていることを確認できる。 `mimizou-libtest/lib/index.js` ```json "use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.hello = void 0; const hello = (name) => "Hello, " + name + "!"; exports.hello = hello; ``` `mimizou-libtest/lib/index.d.ts` ```ts export declare const hello: (name: string) => string; ``` 最後に、それらをエントリポイントと設定するため、[[package.json]]の`main`と`types`を更新する。また、利用側で必要なもののみを提供するため、[[files (npm)|files]]に`lib`のみを指定する。 `mimizou-libtest/package.json` ```json { "name": "@tadashi-aikawa/mimizou-lib-test", "main": "lib/index.js", "types": "lib/index.d.ts", "files": ["lib"], "scripts": { "build": "tsc" }, "devDependencies": { "@tsconfig/node18": "^1.0.1", "typescript": "^4.9.5" } } ``` ## ライブラリ利用プロジェクトでリトライ ライブラリ利用プロジェクトに移動して、もう一度インストール。 ```console cd ../mimizou-cli npm i ../mimizou-libtest ``` ビルドをすると成功するはず。 ```console npm run build ``` 実行して動けばOK! ```console $ node lib/index.js Hello world! ```