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)