tsc の3フェーズを trace.json と Compiler API で追ってみた
こんにちは 人材育成室 育成メンバーチームで 研修中の はすと です。
前回書いた、「TypeScript コンパイラが内部で生成する型オブジェクトを覗いてみた」 という記事では、tscが生成する型オブジェクトの構造に焦点を当てたものでした。
しかし型オブジェクトを見たことで、新たな疑問を持ちました。型オブジェクトが生成されるまでに、どんなフェーズを経ているのか? そこで今回は--generateTrace の trace.json を起点に、Compiler APIを使って各フェーズを実際に覗いてみました。
tsc --generateTrace で trace.json を見てみる
tsc 実行時に --generateTrace オプションを付けると、types.json と trace.json の2つが出力されます。前回の記事でも書いた通り、types.json には型オブジェクトが記されており、trace.json にはコンパイル中の処理の流れが記されています。今回は処理の流れを追うために、trace.json を見ていきます。
$ tsc --generateTrace ./trace-output
上記を実行すると、./trace-output/trace.json が出力されます。出力される trace.json は約14,000行の膨大なファイルなので、始めの部分だけ抜粋して見てみます。
[
{
"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" はメタデータを指していて、プロセス名やスレッド名などの情報を意味しています。他にも B と E がありますが、これは 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 の宣言部分だけに絞ってみてみます。
{
"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);
シンボルテーブルも量が多いため、抜粋すると以下のようになります。
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 myName と const 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 と同じものですね。
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の型チェックの仕組みがさらに理解できそうな気がしました。次回はそこを掘り下げていきたいと思います。








