TypeScript Academy · レッスン

簡単なLintツールの構築

Compiler APIを使って独自の診断ツールを作成します。

レッスン 4/413 ステップ

「簡単なLintツールの構築」はCoddyKit上の無料TypeScript Academyレッスンです。 これはレッスン4/4です。 下記で完全なレッスンを無料で読むことができます。その後、ブラウザ内の組み込みコードエディタと24時間対応のAIチューターでハンズオン演習できます。 これはTypeScript Academy学習パスの一部であり、ウェブとCoddyKitアプリ全体で進捗が同期されます。 TypeScript Academyコースには全4レッスンが含まれています。

リンティングツールとは

リンティングツールはソースコードを解析し、スタイルや正しさに関する問題を報告します。TypeScript コンパイラー API を使うと、ESLint プラグインだけでは実現できない、型を考慮したルールを構築できます。

// Goal: warn when console.log is called in TypeScript files

プロジェクトのセットアップ

TypeScript プログラムを読み込み、AST を走査して診断情報を報告する Node.js スクリプトを作成します。

import ts from "typescript";
import path from "path";

const files = ["src/index.ts"];
const program = ts.createProgram(files, { strict: true });

ルールの定義

ルールとは、AST ノードを受け取り、ルール違反があった場合に任意の診断メッセージを返す関数です。

type Diagnostic = { file: string; line: number; message: string };

function noConsoleLog(node: ts.Node, sf: ts.SourceFile): Diagnostic | null {
  if (!ts.isCallExpression(node)) return null;
  const expr = node.expression.getText(sf);
  if (expr !== "console.log") return null;
  const { line } = sf.getLineAndCharacterOfPosition(node.pos);
  return { file: sf.fileName, line: line + 1, message: "No console.log allowed" };
}

AST の走査

各ソースファイルのすべてのノードにすべてのルールを適用する、再帰的な走査処理を記述します。

function walk(
  node: ts.Node,
  sf: ts.SourceFile,
  rules: ((n: ts.Node, sf: ts.SourceFile) => Diagnostic | null)[]
): Diagnostic[] {
  const diags: Diagnostic[] = [];
  for (const rule of rules) {
    const d = rule(node, sf);
    if (d) diags.push(d);
  }
  ts.forEachChild(node, child => diags.push(...walk(child, sf, rules)));
  return diags;
}

リンターの実行

すべてのソースファイルをループし、ルールを適用して診断情報を出力します。

const rules = [noConsoleLog];
const allDiagnostics: Diagnostic[] = [];

for (const sf of program.getSourceFiles()) {
  if (!sf.isDeclarationFile) {
    allDiagnostics.push(...walk(sf, sf, rules));
  }
}

allDiagnostics.forEach(d =>
  console.log(`${d.file}:${d.line} — ${d.message}`)
);

型を考慮したルールの追加

型チェッカーを使うと、式の TypeScript 型に依存するルールを構築できます。

const checker = program.getTypeChecker();

function noAnyReturn(node: ts.Node, sf: ts.SourceFile): Diagnostic | null {
  if (!ts.isFunctionDeclaration(node)) return null;
  const sig = checker.getSignatureFromDeclaration(node);
  if (!sig) return null;
  const ret = checker.getReturnTypeOfSignature(sig);
  if (ret.flags & ts.TypeFlags.Any) {
    const { line } = sf.getLineAndCharacterOfPosition(node.pos);
    return { file: sf.fileName, line: line + 1, message: "Function returns any" };
  }
  return null;
}

CI 用の終了コード

診断情報が見つかったときにゼロ以外の終了コードを返し、CI パイプラインでビルドを失敗させます。

if (allDiagnostics.length > 0) {
  console.error(`${allDiagnostics.length} lint error(s)`);
  process.exit(1);
}
process.exit(0);

ルール: 未使用変数の禁止

コンパイラー API はts.getPreEmitDiagnosticsを通じて未使用変数の診断情報を提供するため、組み込みチェックでカスタムルールを補完できます。

const preEmit = ts.getPreEmitDiagnostics(program);
preEmit.forEach(d => {
  const msg = ts.flattenDiagnosticMessageText(d.messageText, "
");
  console.log(msg);
});

ルール: 返り値の型を必須にする

関数に明示的な返り値の型注釈がない場合に警告するルールは、ドキュメントを適切に記述する習慣の徹底に役立ちます。

function requireReturnType(node: ts.Node, sf: ts.SourceFile): Diagnostic | null {
  if (!ts.isFunctionDeclaration(node)) return null;
  if (!node.type) {
    const { line } = sf.getLineAndCharacterOfPosition(node.pos);
    return { file: sf.fileName, line: line + 1, message: "Missing return type" };
  }
  return null;
}

ESLint との比較

カスタムリンターは ESLint を補完します。スタイルのルールには ESLint を使用し、ESLint では表現できない型を考慮したルールには TypeScript コンパイラー API ツールを使用します。

// ESLint: stylistic and common pattern rules
// Compiler API linter: deep type reasoning, custom constraints

まとめ: リンターの構築

TypeScript コンパイラー API のリンターでは、プログラムを作成し、ルールを使って AST を走査し、必要に応じて型チェッカーを参照し、エラーがあればゼロ以外の終了コードで終了します。この方法により、本当に型を考慮した lint ルールを実現できます。

理解度チェック

コンパイラー API のリンターが ESLint より有利なのはなぜですか?

学習内容

コンパイラー API を使って、シンプルな TypeScript リンターを構築しました。プログラムを読み込み、AST を走査し、ルール(必要に応じて型を考慮)を適用して診断情報を報告します。これは、あらゆる TypeScript プロジェクトでカスタム静的解析を行うための基盤になります。

無料で開始

AI チューターと学ぶ TypeScript — 無料

ブラウザでリアルコードを書いて実行し、24/7 の AI チューターから瞬時にサポートを受け、ウェブまたはアプリで続きから学習できます。

コース
101
レッスン
352

よくある質問

「簡単なLintツールの構築」レッスンは無料ですか?

はい。「簡単なLintツールの構築」の完全なテキストはこのウェブで無料で読めます。インタラクティブに演習し(組み込みコードエディタと24時間対応のAIチューター)、TypeScript Academyコースの残りをアンロックするには、CoddyKit PROにアップグレードしてください。 TypeScript Academyコースには全4レッスンが含まれています。

「簡単なLintツールの構築」で何を学びますか?

Compiler APIを使って独自の診断ツールを作成します。 ブラウザで直接実行するハンズオンコードでTypeScript Academyを演習し、24時間対応のAIチューターがレッスンを進める中での質問に答えます。

TypeScript Academyを始めるのに経験は必要ですか?

事前経験は必要ありません。CoddyKitのTypeScript Academyは初級者から上級者向けに構成されているため、ここから始めるか最初から始めて、自分のペースで進むことができます。 これはレッスン4/4です。

「簡単なLintツールの構築」レッスンにはどのくらい時間がかかりますか?

ほとんどのCoddyKitレッスンは約5~10分かかります。各レッスンはコンパクトでインタラクティブなので、着実に進歩し、ウェブとアプリ全体で正確に前回の場所から再開できます。

このTypeScript Academyレッスンでコードを書いて実行できますか?

はい。すべてのTypeScript Academyレッスンに組み込みコードエディタが含まれているため、ブラウザでリアルコードを書いて実行し、即座のAIフィードバックを取得できます。ローカル設定は不要です。

このコースのすべてのレッスン

  1. APIによるTypeScriptプログラムの作成
  2. VisitorによるASTの走査
  3. カスタムTransformerとコード生成
  4. 簡単なLintツールの構築
← TypeScript Academyに戻る