tsc の3フェーズを trace.json と Compiler API で追ってみた

tsc の3フェーズを trace.json と Compiler API で追ってみた

2026.03.14

こんにちは 人材育成室 育成メンバーチームで 研修中の はすと です。

前回書いた、「TypeScript コンパイラが内部で生成する型オブジェクトを覗いてみた」 という記事では、tscが生成する型オブジェクトの構造に焦点を当てたものでした。
しかし型オブジェクトを見たことで、新たな疑問を持ちました。型オブジェクトが生成されるまでに、どんなフェーズを経ているのか? そこで今回は--generateTracetrace.json を起点に、Compiler APIを使って各フェーズを実際に覗いてみました。

tsc --generateTrace で trace.json を見てみる

tsc 実行時に --generateTrace オプションを付けると、types.jsontrace.json の2つが出力されます。前回の記事でも書いた通り、types.json には型オブジェクトが記されており、trace.json にはコンパイル中の処理の流れが記されています。今回は処理の流れを追うために、trace.json を見ていきます。

$ tsc --generateTrace ./trace-output

上記を実行すると、./trace-output/trace.json が出力されます。出力される trace.json は約14,000行の膨大なファイルなので、始めの部分だけ抜粋して見てみます。

trace.json
[
  {
    "name": "process_name",
    "args": { "name": "tsc" },
    "cat": "__metadata",
    "ph": "M",
    "ts": 143026.541,
    "pid": 1,
    "tid": 1
  },
  {
    "name": "thread_name",
    "args": { "name": "Main" },
    "cat": "__metadata",
    "ph": "M",
    "ts": 143026.541,
    "pid": 1,
    "tid": 1
  },
  {
    "name": "TracingStartedInBrowser",
    "cat": "disabled-by-default-devtools.timeline",
    "ph": "M",
    "ts": 143026.541,
    "pid": 1,
    "tid": 1
  },
  {
    "pid": 1,
    "tid": 1,
    "ph": "B",
    "cat": "program",
    "ts": 143962.166,
    "name": "createProgram",
    "args": {
      "configFilePath": "/Users/sasaki.hasuto/develop/ts-engine-lab/tsconfig.json"
    }
  },
  {
    "pid": 1,
    "tid": 1,
    "ph": "B",
    "cat": "parse",
    "ts": 144718.45799999998,
    "name": "createSourceFile",
    "args": {
      "path": "/Users/sasaki.hasuto/develop/ts-engine-lab/src/sample.ts"
    }
  },
  {
    "pid": 1,
    "tid": 1,
    "ph": "E",
    "cat": "parse",
    "ts": 145572.666,
    "name": "createSourceFile",
    "args": {
      "path": "/Users/sasaki.hasuto/develop/ts-engine-lab/src/sample.ts"
    }
  },
  {
    "pid": 1,
    "tid": 1,
    "ph": "B",
    "cat": "parse",
    "ts": 147933.041,
    "name": "createSourceFile",
    "args": {
      "path": "/Users/sasaki.hasuto/develop/ts-engine-lab/node_modules/.pnpm/@types+node@25.4.0/node_modules/@types/node/index.d.ts"
    }
  },
....
]

一番初めの "name": "process_name""args": { "name": "tsc" } はまさに、tscプロセスの開始が記されています。もう一つ注目なのが ph で、これは "phase(フェーズ)" の略語でイベントの種類を表しています。tscプロセスについている ph: "M" はメタデータを指していて、プロセス名やスレッド名などの情報を意味しています。他にも BE がありますが、これは Begin:処理の開始End:処理の終了 を意味しています。この2つを追うことで処理の開始と終了を追うことができるため、流れを見ることができます。

続いては、どの処理が何回実行されたか集計してみます。

集計コマンド
cat trace-output/trace.json | jq 'group_by(.name) | map({name: .[0].name, count: length}) | sort_by(-.count)'
結果
[
  {
    "name": "bindSourceFile",
    "count": 390
  },
  {
    "name": "checkSourceFile",
    "count": 390
  },
  {
    "name": "createSourceFile",
    "count": 390
  },
  {
    "name": "structuredTypeRelatedTo",
    "count": 69
  },
  {
    "name": "findSourceFile",
    "count": 23
  },
  {
    "name": "checkVariableDeclaration",
    "count": 3
  },
  {
    "name": "createProgram",
    "count": 2
  },
  {
    "name": "emit",
    "count": 2
  },
  {
    "name": "emitBuildInfo",
    "count": 2
  },
  {
    "name": "TracingStartedInBrowser",
    "count": 1
  },
  {
    "name": "processTypeReferenceDirective",
    "count": 1
  },
  {
    "name": "processTypeReferences",
    "count": 1
  },
  {
    "name": "process_name",
    "count": 1
  },
  {
    "name": "resolveLibrary",
    "count": 1
  },
  {
    "name": "resolveModuleNamesWorker",
    "count": 1
  },
  {
    "name": "thread_name",
    "count": 1
  }
]

集計の結果、bindSourceFile, checkSourceFile, createSourceFile の3つが同数で最も多く、それぞれ390件ありました。サンプルコードはたった2行でしたが、それだけでもこの3つの処理が390回ずつ走っていることがわかりました。

それぞれの処理について

createSourceFile :TypeScriptのソースコードからASTノード構造を出力します。
bindSourceFile:ASTからシンボルテーブルを生成します。
checkSourceFile:シンボルテーブルをもとに型チェックを行い、型オブジェクトを生成します。

3つの処理の概要がわかったところで、次は Compiler API を使って実際に各フェーズの出力を覗いてみます。

Compiler APIで覗いてみる

createSourceFile:ASTを見る

typescipt パッケージに入っている tsオブジェクトのcreateSourceFileメソッドを使うことで、実際に手元でcreateSourceFileを実行し、ASTを出力することができます。

import * as ts from "typescript";
import * as fs from "fs";

const source = fs.readFileSync("src/sample.ts", "utf-8");
const sourceFile = ts.createSourceFile(
  "sample.ts",
  source,
  ts.ScriptTarget.ES2020
);
console.log(JSON.stringify(sourceFile, null, 2));

上記を実行すると ログとしてASTが出力されるのですが量が多いため、今回書いたサンプルコードの myName の宣言部分だけに絞ってみてみます。

myName部分だけ抜粋
{
  "kind": 261,
  "name": {
    "kind": 80,
    "escapedText": "myName"
  },
  "type": {
    "kind": 154
  },
  "initializer": {
    "kind": 11,
    "text": "hasuto"
  }
}

出力されたAST全体を見てもわかるのですが、ASTの各ノードには kind プロパティがついています。これはノードの種類を表す数字で、1番はEndOfFileTokenという風に割り当てられています。ts.SyntaxKind を使うと数字を人間が読める名前に変換できるため、今回出てきた番号についてみてみましょう。

console.log(ts.SyntaxKind[261]);
console.log(ts.SyntaxKind[80]); 
console.log(ts.SyntaxKind[154]);
console.log(ts.SyntaxKind[11]);
VariableDeclaration // const myName: string = "hasuto" の宣言全体
Identifier          // myName(変数名)
StringKeyword       // string(型)
StringLiteral       // "hasuto"(値)

面白いですね。たった2行のコードでもASTとして細かくノードに分解されていることがわかりました。

出力されたAST
{
  "pos": 0,
  "end": 57,
  "kind": 308,
  "id": 0,
  "flags": 0,
  "modifierFlagsCache": 0,
  "transformFlags": 4457473,
  "statements": [
    {
      "pos": 0,
      "end": 32,
      "kind": 244,
      "id": 0,
      "flags": 0,
      "modifierFlagsCache": 0,
      "transformFlags": 4457473,
      "declarationList": {
        "pos": 0,
        "end": 31,
        "kind": 262,
        "id": 0,
        "flags": 2,
        "modifierFlagsCache": 0,
        "transformFlags": 4457473,
        "declarations": [
          {
            "pos": 5,
            "end": 31,
            "kind": 261,
            "id": 0,
            "flags": 0,
            "modifierFlagsCache": 0,
            "transformFlags": 1,
            "name": {
              "pos": 5,
              "end": 12,
              "kind": 80,
              "id": 0,
              "flags": 0,
              "transformFlags": 0,
              "escapedText": "myName"
            },
            "type": {
              "pos": 13,
              "end": 20,
              "kind": 154,
              "id": 0,
              "flags": 0,
              "transformFlags": 1
            },
            "initializer": {
              "pos": 22,
              "end": 31,
              "kind": 11,
              "id": 0,
              "flags": 0,
              "modifierFlagsCache": 0,
              "transformFlags": 0,
              "text": "hasuto",
              "hasExtendedUnicodeEscape": false
            }
          }
        ]
      }
    },
    {
      "pos": 32,
      "end": 56,
      "kind": 244,
      "id": 0,
      "flags": 0,
      "modifierFlagsCache": 0,
      "transformFlags": 4457473,
      "declarationList": {
        "pos": 32,
        "end": 55,
        "kind": 262,
        "id": 0,
        "flags": 2,
        "modifierFlagsCache": 0,
        "transformFlags": 4457473,
        "declarations": [
          {
            "pos": 38,
            "end": 55,
            "kind": 261,
            "id": 0,
            "flags": 0,
            "modifierFlagsCache": 0,
            "transformFlags": 1,
            "name": {
              "pos": 38,
              "end": 42,
              "kind": 80,
              "id": 0,
              "flags": 0,
              "transformFlags": 0,
              "escapedText": "age"
            },
            "type": {
              "pos": 43,
              "end": 50,
              "kind": 150,
              "id": 0,
              "flags": 0,
              "transformFlags": 1
            },
            "initializer": {
              "pos": 52,
              "end": 55,
              "kind": 9,
              "id": 0,
              "flags": 0,
              "modifierFlagsCache": 0,
              "transformFlags": 0,
              "text": "23",
              "numericLiteralFlags": 0
            }
          }
        ]
      }
    }
  ],
  "endOfFileToken": {
    "pos": 56,
    "end": 57,
    "kind": 1,
    "id": 0,
    "flags": 0,
    "transformFlags": 0
  },
  "text": "const myName: string = \"hasuto\";\nconst age: number = 23;\n",
  "fileName": "sample.ts",
  "path": "",
  "resolvedPath": "",
  "originalFileName": "",
  "languageVersion": 7,
  "languageVariant": 0,
  "scriptKind": 3,
  "isDeclarationFile": false,
  "hasNoDefaultLib": false,
  "nodeCount": 14,
  "identifierCount": 2,
  "symbolCount": 0,
  "parseDiagnostics": [],
  "bindDiagnostics": [],
  "pragmas": {},
  "referencedFiles": [],
  "typeReferenceDirectives": [],
  "libReferenceDirectives": [],
  "amdDependencies": [],
  "identifiers": {},
  "jsDocParsingMode": 0
}

次は bindSourceFile で、このASTからシンボルテーブルがどう生成されるかを見ていきます。

bindSourceFile:シンボルを見る

実は、bindSourceFile はCompiler APIとして外部公開されていないため、直接呼び出すことはできません。そのため、ASTからシンボルテーブルを取得する流れを、Compiler APIの公開されているメソッドを使って再現してみます。

import * as ts from "typescript";

const program = ts.createProgram(["src/sample.ts"], { // Programを作成(内部でcreateSourceFileが呼ばれる)
  lib: ["es2020"],
});
const checker = program.getTypeChecker(); // TypeCheckerを取得(シンボルテーブルへのインターフェース)
const sourceFile = program.getSourceFile("src/sample.ts")!; // AST取得

function visit(node: ts.Node) {
  if (ts.isVariableDeclaration(node)) {
    const symbol = checker.getSymbolAtLocation(node.name);
    if (!symbol) return;
    console.log(symbol);
  }
  ts.forEachChild(node, visit);
}
visit(sourceFile);

シンボルテーブルも量が多いため、抜粋すると以下のようになります。

Symbol 抜粋版
SymbolObject {
  flags: 2,
  escapedName: 'myName',
  declarations: [...],
  ...
}
SymbolObject {
  flags: 2,
  escapedName: 'age',
  declarations: [...],
  ...
}

サンプルコードで宣言した変数が、SymbolObject として定義されていて、flags:シンボルの種類escapedName:変数名declarations:ASTノードへの参照 などが入っています。

今回宣言した変数が実際何のシンボルになっているのか、ts.SymbolFlags[2] を使って見てみます。

console.log(ts.SymbolFlags[2]); 
> BlockScopedVariable

BlockScopedVariable とはブロックスコープ変数という意味で、const や let で宣言された変数がこれに該当します。サンプルコードの const myNameconst age は const で宣言されているため、BlockScopedVariable になっています。

最後に、checkSourceFile でシンボルテーブルをもとに型チェックを行い、型オブジェクトを生成する流れを見ていきます。

symbol 全体
<ref *1> SymbolObject {
  flags: 2,
  escapedName: 'myName',
  declarations: [
    NodeObject {
      pos: 5,
      end: 31,
      kind: 261,
      id: 0,
      flags: 0,
      modifierFlagsCache: 536870912,
      transformFlags: 1,
      parent: [NodeObject],
      original: undefined,
      emitNode: undefined,
      symbol: [Circular *1],
      localSymbol: undefined,
      name: [IdentifierObject],
      exclamationToken: undefined,
      type: [TokenObject],
      initializer: [NodeObject],
      jsDoc: undefined
    }
  ],
  valueDeclaration: <ref *2> NodeObject {
    pos: 5,
    end: 31,
    kind: 261,
    id: 0,
    flags: 0,
    modifierFlagsCache: 536870912,
    transformFlags: 1,
    parent: NodeObject {
      pos: 0,
      end: 31,
      kind: 262,
      id: 0,
      flags: 2,
      modifierFlagsCache: 0,
      transformFlags: 4457473,
      parent: [NodeObject],
      original: undefined,
      emitNode: undefined,
      declarations: [Array]
    },
    original: undefined,
    emitNode: undefined,
    symbol: [Circular *1],
    localSymbol: undefined,
    name: IdentifierObject {
      pos: 5,
      end: 12,
      kind: 80,
      id: 0,
      flags: 0,
      transformFlags: 0,
      parent: [Circular *2],
      emitNode: undefined,
      escapedText: 'myName',
      jsDoc: undefined,
      flowNode: [Object],
      symbol: undefined
    },
    exclamationToken: undefined,
    type: TokenObject {
      pos: 13,
      end: 20,
      kind: 154,
      id: 0,
      flags: 0,
      transformFlags: 1,
      parent: [Circular *2],
      emitNode: undefined
    },
    initializer: NodeObject {
      pos: 22,
      end: 31,
      kind: 11,
      id: 0,
      flags: 0,
      modifierFlagsCache: 0,
      transformFlags: 0,
      parent: [Circular *2],
      original: undefined,
      emitNode: undefined,
      symbol: undefined,
      localSymbol: undefined,
      text: 'hasuto',
      singleQuote: undefined,
      hasExtendedUnicodeEscape: false
    },
    jsDoc: undefined
  },
  id: 0,
  mergeId: 0,
  parent: undefined,
  members: undefined,
  exports: Map(0) {},
  exportSymbol: undefined,
  constEnumOnlyModule: undefined,
  isReferenced: undefined,
  lastAssignmentPos: undefined,
  links: undefined
}
<ref *1> SymbolObject {
  flags: 2,
  escapedName: 'age',
  declarations: [
    NodeObject {
      pos: 38,
      end: 55,
      kind: 261,
      id: 0,
      flags: 0,
      modifierFlagsCache: 536870912,
      transformFlags: 1,
      parent: [NodeObject],
      original: undefined,
      emitNode: undefined,
      symbol: [Circular *1],
      localSymbol: undefined,
      name: [IdentifierObject],
      exclamationToken: undefined,
      type: [TokenObject],
      initializer: [NodeObject],
      jsDoc: undefined
    }
  ],
  valueDeclaration: <ref *2> NodeObject {
    pos: 38,
    end: 55,
    kind: 261,
    id: 0,
    flags: 0,
    modifierFlagsCache: 536870912,
    transformFlags: 1,
    parent: NodeObject {
      pos: 32,
      end: 55,
      kind: 262,
      id: 0,
      flags: 2,
      modifierFlagsCache: 0,
      transformFlags: 4457473,
      parent: [NodeObject],
      original: undefined,
      emitNode: undefined,
      declarations: [Array]
    },
    original: undefined,
    emitNode: undefined,
    symbol: [Circular *1],
    localSymbol: undefined,
    name: IdentifierObject {
      pos: 38,
      end: 42,
      kind: 80,
      id: 0,
      flags: 0,
      transformFlags: 0,
      parent: [Circular *2],
      emitNode: undefined,
      escapedText: 'age',
      jsDoc: undefined,
      flowNode: [Object],
      symbol: undefined
    },
    exclamationToken: undefined,
    type: TokenObject {
      pos: 43,
      end: 50,
      kind: 150,
      id: 0,
      flags: 0,
      transformFlags: 1,
      parent: [Circular *2],
      emitNode: undefined
    },
    initializer: NodeObject {
      pos: 52,
      end: 55,
      kind: 9,
      id: 0,
      flags: 0,
      modifierFlagsCache: 0,
      transformFlags: 0,
      parent: [Circular *2],
      original: undefined,
      emitNode: undefined,
      symbol: undefined,
      localSymbol: undefined,
      text: '23',
      numericLiteralFlags: 0
    },
    jsDoc: undefined
  },
  id: 0,
  mergeId: 0,
  parent: undefined,
  members: undefined,
  exports: Map(0) {},
  exportSymbol: undefined,
  constEnumOnlyModule: undefined,
  isReferenced: undefined,
  lastAssignmentPos: undefined,
  links: undefined
}

checkSourceFile

先程のbindSourceFileと同様で、checkSourceFileも、Compiler APIとして外部公開されていないため、再現してみます。
checker.getTypeOfSymbol(symbol) の部分以外は、bindSourceFileのものと同じです。

import * as ts from "typescript";

const program = ts.createProgram(["src/sample.ts"], {
  lib: ["es2020"],
});
const checker = program.getTypeChecker();
const sourceFile = program.getSourceFile("src/sample.ts")!;

function visit(node: ts.Node) {
  if (ts.isVariableDeclaration(node)) {
    const symbol = checker.getSymbolAtLocation(node.name);
    if (!symbol) return;
    // シンボルから型情報を取得
    const type = checker.getTypeOfSymbol(symbol);
    console.log(checker.typeToString(type));
  }
  ts.forEachChild(node, visit);
}

visit(sourceFile);

実行すると、こちらも同様で出力される型オブジェクトのサイズが大きいため抜粋してみていきます。

TypeObject {
  flags: 32,
  id: 14,
  intrinsicName: 'string',
}
TypeObject {
  flags: 64,
  id: 15,
  intrinsicName: 'number',
}

flags は型の種類を表すビットフラグで、ts.TypeFlags を使うと人間が読める名前に変換できます。実行してみると 32 が String、64 が Number であることがわかります。intrinsicName は型の名前を表していて、 id は型オブジェクトに割り振られた一意のIDです。前回の記事で見た types.json の id と同じものですね。

ts.TypeFlagsの結果
console.log(ts.TypeFlags[32]);
console.log(ts.TypeFlags[64]);
> String
  Number
型オブジェクト全体
TypeObject {
  flags: 32,
  checker: {
    getNodeCount: [Function: getNodeCount],
    getIdentifierCount: [Function: getIdentifierCount],
    getSymbolCount: [Function: getSymbolCount],
    getTypeCount: [Function: getTypeCount],
    getInstantiationCount: [Function: getInstantiationCount],
    getRelationCacheSizes: [Function: getRelationCacheSizes],
    isUndefinedSymbol: [Function: isUndefinedSymbol],
    isArgumentsSymbol: [Function: isArgumentsSymbol],
    isUnknownSymbol: [Function: isUnknownSymbol],
    getMergedSymbol: [Function: getMergedSymbol],
    symbolIsValue: [Function: symbolIsValue],
    getDiagnostics: [Function: getDiagnostics2],
    getGlobalDiagnostics: [Function: getGlobalDiagnostics],
    getRecursionIdentity: [Function: getRecursionIdentity],
    getUnmatchedProperties: [GeneratorFunction: getUnmatchedProperties],
    getTypeOfSymbolAtLocation: [Function: getTypeOfSymbolAtLocation],
    getTypeOfSymbol: [Function: getTypeOfSymbol],
    getSymbolsOfParameterPropertyDeclaration: [Function: getSymbolsOfParameterPropertyDeclaration],
    getDeclaredTypeOfSymbol: [Function: getDeclaredTypeOfSymbol],
    getPropertiesOfType: [Function: getPropertiesOfType],
    getPropertyOfType: [Function: getPropertyOfType],
    getPrivateIdentifierPropertyOfType: [Function: getPrivateIdentifierPropertyOfType],
    getTypeOfPropertyOfType: [Function: getTypeOfPropertyOfType],
    getIndexInfoOfType: [Function: getIndexInfoOfType],
    getIndexInfosOfType: [Function: getIndexInfosOfType],
    getIndexInfosOfIndexSymbol: [Function: getIndexInfosOfIndexSymbol],
    getSignaturesOfType: [Function: getSignaturesOfType],
    getIndexTypeOfType: [Function: getIndexTypeOfType],
    getIndexType: [Function: getIndexType],
    getBaseTypes: [Function: getBaseTypes],
    getBaseTypeOfLiteralType: [Function: getBaseTypeOfLiteralType],
    getWidenedType: [Function: getWidenedType],
    getWidenedLiteralType: [Function: getWidenedLiteralType],
    fillMissingTypeArguments: [Function: fillMissingTypeArguments],
    getTypeFromTypeNode: [Function: getTypeFromTypeNode],
    getParameterType: [Function: getTypeAtPosition],
    getParameterIdentifierInfoAtPosition: [Function: getParameterIdentifierInfoAtPosition],
    getPromisedTypeOfPromise: [Function: getPromisedTypeOfPromise],
    getAwaitedType: [Function: getAwaitedType],
    getReturnTypeOfSignature: [Function: getReturnTypeOfSignature],
    isNullableType: [Function: isNullableType],
    getNullableType: [Function: getNullableType],
    getNonNullableType: [Function: getNonNullableType],
    getNonOptionalType: [Function: removeOptionalTypeMarker],
    getTypeArguments: [Function: getTypeArguments],
    typeToTypeNode: [Function: typeToTypeNode],
    typePredicateToTypePredicateNode: [Function: typePredicateToTypePredicateNode],
    indexInfoToIndexSignatureDeclaration: [Function: indexInfoToIndexSignatureDeclaration],
    signatureToSignatureDeclaration: [Function: signatureToSignatureDeclaration],
    symbolToEntityName: [Function: symbolToEntityName],
    symbolToExpression: [Function: symbolToExpression],
    symbolToNode: [Function: symbolToNode],
    symbolToTypeParameterDeclarations: [Function: symbolToTypeParameterDeclarations],
    symbolToParameterDeclaration: [Function: symbolToParameterDeclaration],
    typeParameterToDeclaration: [Function: typeParameterToDeclaration],
    getSymbolsInScope: [Function: getSymbolsInScope],
    getSymbolAtLocation: [Function: getSymbolAtLocation],
    getIndexInfosAtLocation: [Function: getIndexInfosAtLocation],
    getShorthandAssignmentValueSymbol: [Function: getShorthandAssignmentValueSymbol],
    getExportSpecifierLocalTargetSymbol: [Function: getExportSpecifierLocalTargetSymbol],
    getExportSymbolOfSymbol: [Function: getExportSymbolOfSymbol],
    getTypeAtLocation: [Function: getTypeAtLocation],
    getTypeOfAssignmentPattern: [Function: getTypeOfAssignmentPattern],
    getPropertySymbolOfDestructuringAssignment: [Function: getPropertySymbolOfDestructuringAssignment],
    signatureToString: [Function: signatureToString],
    typeToString: [Function: typeToString],
    symbolToString: [Function: symbolToString],
    typePredicateToString: [Function: typePredicateToString],
    writeSignature: [Function: writeSignature],
    writeType: [Function: writeType],
    writeSymbol: [Function: writeSymbol],
    writeTypePredicate: [Function: writeTypePredicate],
    getAugmentedPropertiesOfType: [Function: getAugmentedPropertiesOfType],
    getRootSymbols: [Function: getRootSymbols],
    getSymbolOfExpando: [Function: getSymbolOfExpando],
    getContextualType: [Function: getContextualType],
    getContextualTypeForObjectLiteralElement: [Function: getContextualTypeForObjectLiteralElement],
    getContextualTypeForArgumentAtIndex: [Function: getContextualTypeForArgumentAtIndex],
    getContextualTypeForJsxAttribute: [Function: getContextualTypeForJsxAttribute],
    isContextSensitive: [Function: isContextSensitive],
    getTypeOfPropertyOfContextualType: [Function: getTypeOfPropertyOfContextualType],
    getFullyQualifiedName: [Function: getFullyQualifiedName],
    getResolvedSignature: [Function: getResolvedSignature],
    getCandidateSignaturesForStringLiteralCompletions: [Function: getCandidateSignaturesForStringLiteralCompletions],
    getResolvedSignatureForSignatureHelp: [Function: getResolvedSignatureForSignatureHelp],
    getExpandedParameters: [Function: getExpandedParameters],
    hasEffectiveRestParameter: [Function: hasEffectiveRestParameter],
    containsArgumentsReference: [Function: containsArgumentsReference],
    getConstantValue: [Function: getConstantValue],
    isValidPropertyAccess: [Function: isValidPropertyAccess],
    isValidPropertyAccessForCompletions: [Function: isValidPropertyAccessForCompletions],
    getSignatureFromDeclaration: [Function: getSignatureFromDeclaration],
    isImplementationOfOverload: [Function: isImplementationOfOverload],
    getImmediateAliasedSymbol: [Function: getImmediateAliasedSymbol],
    getAliasedSymbol: [Function: resolveAlias],
    getEmitResolver: [Function: getEmitResolver],
    requiresAddingImplicitUndefined: [Function: requiresAddingImplicitUndefined],
    getExportsOfModule: [Function: getExportsOfModuleAsArray],
    getExportsAndPropertiesOfModule: [Function: getExportsAndPropertiesOfModule],
    forEachExportAndPropertyOfModule: [Function: forEachExportAndPropertyOfModule],
    getSymbolWalker: [Function: getSymbolWalker],
    getAmbientModules: [Function: getAmbientModules],
    getJsxIntrinsicTagNamesAt: [Function: getJsxIntrinsicTagNamesAt],
    isOptionalParameter: [Function: isOptionalParameter],
    tryGetMemberInModuleExports: [Function: tryGetMemberInModuleExports],
    tryGetMemberInModuleExportsAndProperties: [Function: tryGetMemberInModuleExportsAndProperties],
    tryFindAmbientModule: [Function: tryFindAmbientModule],
    getApparentType: [Function: getApparentType],
    getUnionType: [Function: getUnionType],
    isTypeAssignableTo: [Function: isTypeAssignableTo],
    createAnonymousType: [Function: createAnonymousType],
    createSignature: [Function: createSignature],
    createSymbol: [Function: createSymbol],
    createIndexInfo: [Function: createIndexInfo],
    getAnyType: [Function: getAnyType],
    getStringType: [Function: getStringType],
    getStringLiteralType: [Function: getStringLiteralType],
    getNumberType: [Function: getNumberType],
    getNumberLiteralType: [Function: getNumberLiteralType],
    getBigIntType: [Function: getBigIntType],
    getBigIntLiteralType: [Function: getBigIntLiteralType],
    getUnknownType: [Function: getUnknownType],
    createPromiseType: [Function: createPromiseType],
    createArrayType: [Function: createArrayType],
    getElementTypeOfArrayType: [Function: getElementTypeOfArrayType],
    getBooleanType: [Function: getBooleanType],
    getFalseType: [Function: getFalseType],
    getTrueType: [Function: getTrueType],
    getVoidType: [Function: getVoidType],
    getUndefinedType: [Function: getUndefinedType],
    getNullType: [Function: getNullType],
    getESSymbolType: [Function: getESSymbolType],
    getNeverType: [Function: getNeverType],
    getNonPrimitiveType: [Function: getNonPrimitiveType],
    getOptionalType: [Function: getOptionalType],
    getPromiseType: [Function: getPromiseType],
    getPromiseLikeType: [Function: getPromiseLikeType],
    getAnyAsyncIterableType: [Function: getAnyAsyncIterableType],
    isSymbolAccessible: [Function: isSymbolAccessible],
    isArrayType: [Function: isArrayType],
    isTupleType: [Function: isTupleType],
    isArrayLikeType: [Function: isArrayLikeType],
    isEmptyAnonymousObjectType: [Function: isEmptyAnonymousObjectType],
    isTypeInvalidDueToUnionDiscriminant: [Function: isTypeInvalidDueToUnionDiscriminant],
    getExactOptionalProperties: [Function: getExactOptionalProperties],
    getAllPossiblePropertiesOfTypes: [Function: getAllPossiblePropertiesOfTypes],
    getSuggestedSymbolForNonexistentProperty: [Function: getSuggestedSymbolForNonexistentProperty],
    getSuggestedSymbolForNonexistentJSXAttribute: [Function: getSuggestedSymbolForNonexistentJSXAttribute],
    getSuggestedSymbolForNonexistentSymbol: [Function: getSuggestedSymbolForNonexistentSymbol],
    getSuggestedSymbolForNonexistentModule: [Function: getSuggestedSymbolForNonexistentModule],
    getSuggestedSymbolForNonexistentClassMember: [Function: getSuggestedSymbolForNonexistentClassMember],
    getBaseConstraintOfType: [Function: getBaseConstraintOfType],
    getDefaultFromTypeParameter: [Function: getDefaultFromTypeParameter],
    resolveName: [Function: resolveName],
    getJsxNamespace: [Function: getJsxNamespace],
    getJsxFragmentFactory: [Function: getJsxFragmentFactory],
    getAccessibleSymbolChain: [Function: getAccessibleSymbolChain],
    getTypePredicateOfSignature: [Function: getTypePredicateOfSignature],
    resolveExternalModuleName: [Function: resolveExternalModuleName],
    resolveExternalModuleSymbol: [Function: resolveExternalModuleSymbol],
    tryGetThisTypeAt: [Function: tryGetThisTypeAt],
    getTypeArgumentConstraint: [Function: getTypeArgumentConstraint],
    getSuggestionDiagnostics: [Function: getSuggestionDiagnostics],
    runWithCancellationToken: [Function: runWithCancellationToken],
    getLocalTypeParametersOfClassOrInterfaceOrTypeAlias: [Function: getLocalTypeParametersOfClassOrInterfaceOrTypeAlias],
    isDeclarationVisible: [Function: isDeclarationVisible],
    isPropertyAccessible: [Function: isPropertyAccessible],
    getTypeOnlyAliasDeclaration: [Function: getTypeOnlyAliasDeclaration],
    getMemberOverrideModifierStatus: [Function: getMemberOverrideModifierStatus],
    isTypeParameterPossiblyReferenced: [Function: isTypeParameterPossiblyReferenced],
    typeHasCallOrConstructSignatures: [Function: typeHasCallOrConstructSignatures],
    getSymbolFlags: [Function: getSymbolFlags],
    getTypeArgumentsForResolvedSignature: [Function: getTypeArgumentsForResolvedSignature],
    isLibType: [Function: isLibType]
  },
  id: 14,
  intrinsicName: 'string',
  debugIntrinsicName: undefined,
  objectFlags: 52953088
}
TypeObject {
  flags: 64,
  checker: {
    getNodeCount: [Function: getNodeCount],
    getIdentifierCount: [Function: getIdentifierCount],
    getSymbolCount: [Function: getSymbolCount],
    getTypeCount: [Function: getTypeCount],
    getInstantiationCount: [Function: getInstantiationCount],
    getRelationCacheSizes: [Function: getRelationCacheSizes],
    isUndefinedSymbol: [Function: isUndefinedSymbol],
    isArgumentsSymbol: [Function: isArgumentsSymbol],
    isUnknownSymbol: [Function: isUnknownSymbol],
    getMergedSymbol: [Function: getMergedSymbol],
    symbolIsValue: [Function: symbolIsValue],
    getDiagnostics: [Function: getDiagnostics2],
    getGlobalDiagnostics: [Function: getGlobalDiagnostics],
    getRecursionIdentity: [Function: getRecursionIdentity],
    getUnmatchedProperties: [GeneratorFunction: getUnmatchedProperties],
    getTypeOfSymbolAtLocation: [Function: getTypeOfSymbolAtLocation],
    getTypeOfSymbol: [Function: getTypeOfSymbol],
    getSymbolsOfParameterPropertyDeclaration: [Function: getSymbolsOfParameterPropertyDeclaration],
    getDeclaredTypeOfSymbol: [Function: getDeclaredTypeOfSymbol],
    getPropertiesOfType: [Function: getPropertiesOfType],
    getPropertyOfType: [Function: getPropertyOfType],
    getPrivateIdentifierPropertyOfType: [Function: getPrivateIdentifierPropertyOfType],
    getTypeOfPropertyOfType: [Function: getTypeOfPropertyOfType],
    getIndexInfoOfType: [Function: getIndexInfoOfType],
    getIndexInfosOfType: [Function: getIndexInfosOfType],
    getIndexInfosOfIndexSymbol: [Function: getIndexInfosOfIndexSymbol],
    getSignaturesOfType: [Function: getSignaturesOfType],
    getIndexTypeOfType: [Function: getIndexTypeOfType],
    getIndexType: [Function: getIndexType],
    getBaseTypes: [Function: getBaseTypes],
    getBaseTypeOfLiteralType: [Function: getBaseTypeOfLiteralType],
    getWidenedType: [Function: getWidenedType],
    getWidenedLiteralType: [Function: getWidenedLiteralType],
    fillMissingTypeArguments: [Function: fillMissingTypeArguments],
    getTypeFromTypeNode: [Function: getTypeFromTypeNode],
    getParameterType: [Function: getTypeAtPosition],
    getParameterIdentifierInfoAtPosition: [Function: getParameterIdentifierInfoAtPosition],
    getPromisedTypeOfPromise: [Function: getPromisedTypeOfPromise],
    getAwaitedType: [Function: getAwaitedType],
    getReturnTypeOfSignature: [Function: getReturnTypeOfSignature],
    isNullableType: [Function: isNullableType],
    getNullableType: [Function: getNullableType],
    getNonNullableType: [Function: getNonNullableType],
    getNonOptionalType: [Function: removeOptionalTypeMarker],
    getTypeArguments: [Function: getTypeArguments],
    typeToTypeNode: [Function: typeToTypeNode],
    typePredicateToTypePredicateNode: [Function: typePredicateToTypePredicateNode],
    indexInfoToIndexSignatureDeclaration: [Function: indexInfoToIndexSignatureDeclaration],
    signatureToSignatureDeclaration: [Function: signatureToSignatureDeclaration],
    symbolToEntityName: [Function: symbolToEntityName],
    symbolToExpression: [Function: symbolToExpression],
    symbolToNode: [Function: symbolToNode],
    symbolToTypeParameterDeclarations: [Function: symbolToTypeParameterDeclarations],
    symbolToParameterDeclaration: [Function: symbolToParameterDeclaration],
    typeParameterToDeclaration: [Function: typeParameterToDeclaration],
    getSymbolsInScope: [Function: getSymbolsInScope],
    getSymbolAtLocation: [Function: getSymbolAtLocation],
    getIndexInfosAtLocation: [Function: getIndexInfosAtLocation],
    getShorthandAssignmentValueSymbol: [Function: getShorthandAssignmentValueSymbol],
    getExportSpecifierLocalTargetSymbol: [Function: getExportSpecifierLocalTargetSymbol],
    getExportSymbolOfSymbol: [Function: getExportSymbolOfSymbol],
    getTypeAtLocation: [Function: getTypeAtLocation],
    getTypeOfAssignmentPattern: [Function: getTypeOfAssignmentPattern],
    getPropertySymbolOfDestructuringAssignment: [Function: getPropertySymbolOfDestructuringAssignment],
    signatureToString: [Function: signatureToString],
    typeToString: [Function: typeToString],
    symbolToString: [Function: symbolToString],
    typePredicateToString: [Function: typePredicateToString],
    writeSignature: [Function: writeSignature],
    writeType: [Function: writeType],
    writeSymbol: [Function: writeSymbol],
    writeTypePredicate: [Function: writeTypePredicate],
    getAugmentedPropertiesOfType: [Function: getAugmentedPropertiesOfType],
    getRootSymbols: [Function: getRootSymbols],
    getSymbolOfExpando: [Function: getSymbolOfExpando],
    getContextualType: [Function: getContextualType],
    getContextualTypeForObjectLiteralElement: [Function: getContextualTypeForObjectLiteralElement],
    getContextualTypeForArgumentAtIndex: [Function: getContextualTypeForArgumentAtIndex],
    getContextualTypeForJsxAttribute: [Function: getContextualTypeForJsxAttribute],
    isContextSensitive: [Function: isContextSensitive],
    getTypeOfPropertyOfContextualType: [Function: getTypeOfPropertyOfContextualType],
    getFullyQualifiedName: [Function: getFullyQualifiedName],
    getResolvedSignature: [Function: getResolvedSignature],
    getCandidateSignaturesForStringLiteralCompletions: [Function: getCandidateSignaturesForStringLiteralCompletions],
    getResolvedSignatureForSignatureHelp: [Function: getResolvedSignatureForSignatureHelp],
    getExpandedParameters: [Function: getExpandedParameters],
    hasEffectiveRestParameter: [Function: hasEffectiveRestParameter],
    containsArgumentsReference: [Function: containsArgumentsReference],
    getConstantValue: [Function: getConstantValue],
    isValidPropertyAccess: [Function: isValidPropertyAccess],
    isValidPropertyAccessForCompletions: [Function: isValidPropertyAccessForCompletions],
    getSignatureFromDeclaration: [Function: getSignatureFromDeclaration],
    isImplementationOfOverload: [Function: isImplementationOfOverload],
    getImmediateAliasedSymbol: [Function: getImmediateAliasedSymbol],
    getAliasedSymbol: [Function: resolveAlias],
    getEmitResolver: [Function: getEmitResolver],
    requiresAddingImplicitUndefined: [Function: requiresAddingImplicitUndefined],
    getExportsOfModule: [Function: getExportsOfModuleAsArray],
    getExportsAndPropertiesOfModule: [Function: getExportsAndPropertiesOfModule],
    forEachExportAndPropertyOfModule: [Function: forEachExportAndPropertyOfModule],
    getSymbolWalker: [Function: getSymbolWalker],
    getAmbientModules: [Function: getAmbientModules],
    getJsxIntrinsicTagNamesAt: [Function: getJsxIntrinsicTagNamesAt],
    isOptionalParameter: [Function: isOptionalParameter],
    tryGetMemberInModuleExports: [Function: tryGetMemberInModuleExports],
    tryGetMemberInModuleExportsAndProperties: [Function: tryGetMemberInModuleExportsAndProperties],
    tryFindAmbientModule: [Function: tryFindAmbientModule],
    getApparentType: [Function: getApparentType],
    getUnionType: [Function: getUnionType],
    isTypeAssignableTo: [Function: isTypeAssignableTo],
    createAnonymousType: [Function: createAnonymousType],
    createSignature: [Function: createSignature],
    createSymbol: [Function: createSymbol],
    createIndexInfo: [Function: createIndexInfo],
    getAnyType: [Function: getAnyType],
    getStringType: [Function: getStringType],
    getStringLiteralType: [Function: getStringLiteralType],
    getNumberType: [Function: getNumberType],
    getNumberLiteralType: [Function: getNumberLiteralType],
    getBigIntType: [Function: getBigIntType],
    getBigIntLiteralType: [Function: getBigIntLiteralType],
    getUnknownType: [Function: getUnknownType],
    createPromiseType: [Function: createPromiseType],
    createArrayType: [Function: createArrayType],
    getElementTypeOfArrayType: [Function: getElementTypeOfArrayType],
    getBooleanType: [Function: getBooleanType],
    getFalseType: [Function: getFalseType],
    getTrueType: [Function: getTrueType],
    getVoidType: [Function: getVoidType],
    getUndefinedType: [Function: getUndefinedType],
    getNullType: [Function: getNullType],
    getESSymbolType: [Function: getESSymbolType],
    getNeverType: [Function: getNeverType],
    getNonPrimitiveType: [Function: getNonPrimitiveType],
    getOptionalType: [Function: getOptionalType],
    getPromiseType: [Function: getPromiseType],
    getPromiseLikeType: [Function: getPromiseLikeType],
    getAnyAsyncIterableType: [Function: getAnyAsyncIterableType],
    isSymbolAccessible: [Function: isSymbolAccessible],
    isArrayType: [Function: isArrayType],
    isTupleType: [Function: isTupleType],
    isArrayLikeType: [Function: isArrayLikeType],
    isEmptyAnonymousObjectType: [Function: isEmptyAnonymousObjectType],
    isTypeInvalidDueToUnionDiscriminant: [Function: isTypeInvalidDueToUnionDiscriminant],
    getExactOptionalProperties: [Function: getExactOptionalProperties],
    getAllPossiblePropertiesOfTypes: [Function: getAllPossiblePropertiesOfTypes],
    getSuggestedSymbolForNonexistentProperty: [Function: getSuggestedSymbolForNonexistentProperty],
    getSuggestedSymbolForNonexistentJSXAttribute: [Function: getSuggestedSymbolForNonexistentJSXAttribute],
    getSuggestedSymbolForNonexistentSymbol: [Function: getSuggestedSymbolForNonexistentSymbol],
    getSuggestedSymbolForNonexistentModule: [Function: getSuggestedSymbolForNonexistentModule],
    getSuggestedSymbolForNonexistentClassMember: [Function: getSuggestedSymbolForNonexistentClassMember],
    getBaseConstraintOfType: [Function: getBaseConstraintOfType],
    getDefaultFromTypeParameter: [Function: getDefaultFromTypeParameter],
    resolveName: [Function: resolveName],
    getJsxNamespace: [Function: getJsxNamespace],
    getJsxFragmentFactory: [Function: getJsxFragmentFactory],
    getAccessibleSymbolChain: [Function: getAccessibleSymbolChain],
    getTypePredicateOfSignature: [Function: getTypePredicateOfSignature],
    resolveExternalModuleName: [Function: resolveExternalModuleName],
    resolveExternalModuleSymbol: [Function: resolveExternalModuleSymbol],
    tryGetThisTypeAt: [Function: tryGetThisTypeAt],
    getTypeArgumentConstraint: [Function: getTypeArgumentConstraint],
    getSuggestionDiagnostics: [Function: getSuggestionDiagnostics],
    runWithCancellationToken: [Function: runWithCancellationToken],
    getLocalTypeParametersOfClassOrInterfaceOrTypeAlias: [Function: getLocalTypeParametersOfClassOrInterfaceOrTypeAlias],
    isDeclarationVisible: [Function: isDeclarationVisible],
    isPropertyAccessible: [Function: isPropertyAccessible],
    getTypeOnlyAliasDeclaration: [Function: getTypeOnlyAliasDeclaration],
    getMemberOverrideModifierStatus: [Function: getMemberOverrideModifierStatus],
    isTypeParameterPossiblyReferenced: [Function: isTypeParameterPossiblyReferenced],
    typeHasCallOrConstructSignatures: [Function: typeHasCallOrConstructSignatures],
    getSymbolFlags: [Function: getSymbolFlags],
    getTypeArgumentsForResolvedSignature: [Function: getTypeArgumentsForResolvedSignature],
    isLibType: [Function: isLibType]
  },
  id: 15,
  intrinsicName: 'number',
  debugIntrinsicName: undefined,
  objectFlags: 52953088
}

まとめ

今回は trace.json を起点に、tscの内部で主に3つの処理createSourceFile,bindSourceFile,checkSourceFileが実行されていることを確認することができました。またCompiler APIを使って各フェーズの出力を実際に見ることで、自分が書いたコードがAST・シンボル・型オブジェクトと形を変えていく過程を追うことで、自分の書いたコードがいろんな形に変わりながら生きているんだなという面白さを感じました。
今回は各フェーズで「何が生成されるか」を追いましたが、「なぜこのような処理をするのか」という理由まで深掘れると、TypeScriptの型チェックの仕組みがさらに理解できそうな気がしました。次回はそこを掘り下げていきたいと思います。

この記事をシェアする

FacebookHatena blogX

関連記事