Typescript Compiler API で tsconfig.json を指定する
備忘録。TypeScript の Compiler API を特定の tsconfig.json の設定で使う方法について。
TypeScript のバージョンは 4.1.3。
いつ tsconfig.json の設定が必要か?
例えば tsconfig.json で paths を設定している時。tsconfig.json で以下の設定をしているとする:
{ "compilerOptions": { "baseUrl": "./", "paths": { "@/*": ["./src/*"] }
この設定によって import のパス指定で src/ へのエイリアスとして @/ と書くことができる。
src/point.ts:
export class Point { readonly x: number readonly y: number constructor(x: number, y: number) { this.x = x this.y = y } }
src/main.ts:
import { Point } from "@/point" function dist(p: Point, q: Point): number { return Math.sqrt(Math.pow(p.x - q.x, 2) + Math.pow(p.y - q.y, 2)) } const p = new Point(1, 2) const q = new Point(4, 6) console.log(dist(p, q))
この src/main.ts を Compiler API でパース・解析する時、上記の tsconfig.json の情報が無いと import を解決することができない。
.compilerOptions を Compiler API に渡す方法
createProgram の第2引数にはコンパイラオプション(CompilerOptions 型)を渡すことができる。これは tsconfig.json 内の .compilerOptions と概ね一致している。
ただし tsconfig.json はコメント付き JSON なので、単に JSON.parse で読み込んでも大抵はエラーとなってしまう。readConfigFile を使うとコメント付きの tsconfig.json をパースすることができる。readConfigFile は第2引数としてファイル読み込みを行うコールバック()を受け取るので、fs.readFileSync など適宜適切な関数を渡せばよい。
import * as ts from "typescript" import { readFileSync } from "fs" const readFile: (path: string) => string | undefined = (path) => readFileSync(path, "utf-8") const tsconfig: { config?: any, errors?: ts.Diagnostic; } = ts.readConfigFile("tsconfig.json", readFile) if (tsconfig.errors !== undefined) { throw new Error("cannot load tsconfig") }
正常に読み込めた場合、戻り値オブジェクトの .config に tsconfig.json の中身が入っている。.compilerOptions の内容を CompilerAPI が解釈できる形式に変換するために、convertCompilerOptionsFromJson を使う。
const { options: ts.CompilerOptions, errors: ts.Diagnostic[] } = ts.convertCompilerOptionsFromJson(tsconfig.config.compilerOptions, ".") if (errors.length !== 0) { throw new Error("cannot convert compilerOptions in tsconfig.json") }
手に入れた CompilerOptions オブジェクトを createProgram に渡すことで、paths の設定などを使って TypeScript のコードをパース・解析することができる。
const program: ts.Program = ts.createProgram(["src/main.ts"], compilerOptions)