TypeScript μ»΄νμΌλ¬ APIμ λν μ’ ν© κ°μ΄λλ‘, κ΅μ κ°λ°μλ₯Ό μν AST(Abstract Syntax Trees), μ½λ λΆμ, λ³ν λ° μμ±μ λ€λ£Ήλλ€.
TypeScript μ»΄νμΌλ¬ API: AST μ‘°μ λ° μ½λ λ³ν λ§μ€ν°νκΈ°
TypeScript μ»΄νμΌλ¬ APIλ TypeScript λ° JavaScript μ½λλ₯Ό λΆμ, μ‘°μ λ° μμ±νκΈ° μν κ°λ ₯ν μΈν°νμ΄μ€λ₯Ό μ 곡ν©λλ€. κ·Έ ν΅μ¬μλ μμ€ μ½λμ ꡬ쑰νλ ννμΈ AST(Abstract Syntax Tree)κ° μμ΅λλ€. ASTλ₯Ό μ¬μ©νμ¬ μμ νλ λ°©λ²μ μ΄ν΄νλ©΄ λ¦°ν°, μ½λ ν¬λ§·ν°, μ μ λΆμκΈ° λ° μ¬μ©μ μ μ μ½λ μμ±κΈ°μ κ°μ κ³ κΈ ν΄λ§μ ꡬμΆν μ μμ΅λλ€.
TypeScript μ»΄νμΌλ¬ APIλ 무μμ λκΉ?
TypeScript μ»΄νμΌλ¬ APIλ TypeScript μ»΄νμΌλ¬μ λ΄λΆ μλ λ°©μμ λ ΈμΆνλ TypeScript μΈν°νμ΄μ€ λ° ν¨μμ μ§ν©μ λλ€. μ΄λ₯Ό ν΅ν΄ κ°λ°μλ λ¨μν μ½λλ₯Ό μ»΄νμΌνλ κ² μ΄μμΌλ‘ μ»΄νμΌ νλ‘μΈμ€μ νλ‘κ·Έλλ° λ°©μμΌλ‘ μνΈ μμ©ν μ μμ΅λλ€. λ€μμ μννλ λ° μ¬μ©ν μ μμ΅λλ€.
- μ½λ λΆμ: μ½λ ꡬ쑰λ₯Ό κ²μ¬νκ³ μ μ¬μ μΈ λ¬Έμ λ₯Ό μλ³νλ©° μλ―Έ μ 보λ₯Ό μΆμΆν©λλ€.
- μ½λ λ³ν: κΈ°μ‘΄ μ½λλ₯Ό μμ νκ³ μ κΈ°λ₯μ μΆκ°νκ±°λ μ½λλ₯Ό μλμΌλ‘ 리ν©ν°λ§ν©λλ€.
- μ½λ μμ±: ν νλ¦Ώ λλ κΈ°ν μ λ ₯μ κΈ°λ°μΌλ‘ μ²μλΆν° μ μ½λλ₯Ό λ§λλλ€.
μ΄ APIλ μ½λ νμ§μ κ°μ νκ³ λ°λ³΅μ μΈ μμ μ μλννλ©° κ°λ°μ μμ°μ±μ ν₯μμν€λ μ κ΅ν κ°λ° λꡬλ₯Ό ꡬμΆνλ λ° νμμ μ λλ€.
AST(Abstract Syntax Tree) μ΄ν΄
ASTλ μ½λ ꡬ쑰μ νΈλ¦¬μ κ°μ ννμ λλ€. νΈλ¦¬μ κ° λ Έλλ λ³μ μ μΈ, ν¨μ νΈμΆ λλ μ μ΄ νλ¦ λ¬Έκ³Ό κ°μ ꡬ문 ꡬ문μ λνλ λλ€. TypeScript μ»΄νμΌλ¬ APIλ ASTλ₯Ό νμνκ³ ν΄λΉ λ Έλλ₯Ό κ²μ¬νκ³ μμ νλ λꡬλ₯Ό μ 곡ν©λλ€.
λ€μμ κ°λ¨ν TypeScript μ½λλ₯Ό κ³ λ €ν΄ λ³΄μΈμ.
function greet(name: string): string {
return `Hello, ${name}!`;
}
console.log(greet("World"));
μ΄ μ½λμ λν ASTλ ν¨μ μ μΈ, return λ¬Έ, ν νλ¦Ώ 리ν°λ΄, console.log νΈμΆ λ° μ½λμ κΈ°ν μμλ₯Ό λνλ λλ€. ASTλ₯Ό μκ°ννλ κ²μ μ΄λ €μΈ μ μμ§λ§ AST νμκΈ°(astexplorer.net)μ κ°μ λκ΅¬κ° λμμ΄ λ μ μμ΅λλ€. μ΄λ¬ν λꡬλ₯Ό μ¬μ©νλ©΄ μ½λλ₯Ό μ λ ₯νκ³ ν΄λΉ ASTλ₯Ό μ¬μ©μ μΉνμ μΈ νμμΌλ‘ λ³Ό μ μμ΅λλ€. AST Explorerλ₯Ό μ¬μ©νλ©΄ μ‘°μν μ½λ ꡬ쑰μ μ’ λ₯λ₯Ό μ΄ν΄νλ λ° λμμ΄ λ©λλ€.
μ£Όμ AST λ Έλ μ ν
TypeScript μ»΄νμΌλ¬ APIλ λ€μν AST λ Έλ μ νμ μ μνλ©° κ° μ νμ λ€λ₯Έ ꡬ문 ꡬ문μ λνλ λλ€. λ€μμ λͺ κ°μ§ μΌλ°μ μΈ λ Έλ μ νμ λλ€.
- SourceFile: μ 체 TypeScript νμΌμ λνλ λλ€.
- FunctionDeclaration: ν¨μ μ μλ₯Ό λνλ λλ€.
- VariableDeclaration: λ³μ μ μΈμ λνλ λλ€.
- Identifier: μλ³μ(μ: λ³μ μ΄λ¦, ν¨μ μ΄λ¦)λ₯Ό λνλ λλ€.
- StringLiteral: λ¬Έμμ΄ λ¦¬ν°λ΄μ λνλ λλ€.
- CallExpression: ν¨μ νΈμΆμ λνλ λλ€.
- ReturnStatement: return λ¬Έμ λνλ λλ€.
κ° λ Έλ μ νμλ ν΄λΉ μ½λ μμμ λν μ 보λ₯Ό μ 곡νλ μμ±μ΄ μμ΅λλ€. μλ₯Ό λ€μ΄ `FunctionDeclaration` λ Έλμλ μ΄λ¦, λ§€κ°λ³μ, λ°ν μ ν λ° λ³Έλ¬Έμ λν μμ±μ΄ μμ μ μμ΅λλ€.
μ»΄νμΌλ¬ API μμνκΈ°
μ»΄νμΌλ¬ APIλ₯Ό μ¬μ©νλ €λ©΄ TypeScriptλ₯Ό μ€μΉνκ³ TypeScript ꡬ문μ λν κΈ°λ³Έμ μΈ μ΄ν΄κ° νμν©λλ€. λ€μμ TypeScript νμΌμ μ½κ³ ν΄λΉ ASTλ₯Ό μΆλ ₯νλ λ°©λ²μ 보μ¬μ£Όλ κ°λ¨ν μμ λλ€.
import * as ts from "typescript";
import * as fs from "fs";
const fileName = "example.ts";
const sourceCode = fs.readFileSync(fileName, "utf8");
const sourceFile = ts.createSourceFile(
fileName,
sourceCode,
ts.ScriptTarget.ES2015, // Target ECMAScript version
true // SetParentNodes: true to retain parent references in the AST
);
function printAST(node: ts.Node, indent = 0) {
const indentStr = " ".repeat(indent);
console.log(`${indentStr}${ts.SyntaxKind[node.kind]}`);
node.forEachChild(child => printAST(child, indent + 1));
}
printAST(sourceFile);
μ€λͺ :
- λͺ¨λ κ°μ Έμ€κΈ°: νμΌ μμ€ν μμ μ μν΄ `typescript` λͺ¨λκ³Ό `fs` λͺ¨λμ κ°μ Έμ΅λλ€.
- μμ€ νμΌ μ½κΈ°: `example.ts`λΌλ TypeScript νμΌμ λ΄μ©μ μ½μ΅λλ€. μ΄ μμ μ΄ μλνλ €λ©΄ `example.ts` νμΌμ λ§λ€μ΄μΌ ν©λλ€.
- SourceFile λ§λ€κΈ°: ASTμ 루νΈλ₯Ό λνλ΄λ `SourceFile` κ°μ²΄λ₯Ό λ§λλλ€. `ts.createSourceFile` ν¨μλ μμ€ μ½λλ₯Ό ꡬ문 λΆμνκ³ ASTλ₯Ό μμ±ν©λλ€.
- AST μΆλ ₯: ASTλ₯Ό νμνκ³ κ° λ Έλμ μ’ λ₯λ₯Ό μΆλ ₯νλ μ¬κ· ν¨μ `printAST`λ₯Ό μ μν©λλ€.
- printAST νΈμΆ: `printAST`λ₯Ό νΈμΆνμ¬ λ£¨νΈ `SourceFile` λ Έλμμ AST μΆλ ₯μ μμν©λλ€.
μ΄ μ½λλ₯Ό μ€ννλ €λ©΄ `.ts` νμΌ(μ: `ast-example.ts`)λ‘ μ μ₯νκ³ μΌλΆ TypeScript μ½λκ° ν¬ν¨λ `example.ts` νμΌμ λ§λ λ€μ μ½λλ₯Ό μ»΄νμΌνκ³ μ€νν©λλ€.
tsc ast-example.ts
node ast-example.js
μ΄λ κ² νλ©΄ `example.ts` νμΌμ ASTκ° μ½μμ μΆλ ₯λ©λλ€. μΆλ ₯μλ λ Έλμ κ³μΈ΅ ꡬ쑰μ ν΄λΉ μ νμ΄ νμλ©λλ€. μλ₯Ό λ€μ΄ `FunctionDeclaration`, `Identifier`, `Block` λ° κΈ°ν λ Έλ μ νμ΄ νμλ μ μμ΅λλ€.
AST νμ
μ»΄νμΌλ¬ APIλ ASTλ₯Ό νμνλ λͺ κ°μ§ λ°©λ²μ μ 곡ν©λλ€. κ°μ₯ κ°λ¨ν λ°©λ²μ μ΄μ μμμμ κ°μ΄ `forEachChild` λ©μλλ₯Ό μ¬μ©νλ κ²μ λλ€. μ΄ λ©μλλ μ§μ λ λ Έλμ κ° μμ λ Έλλ₯Ό λ°©λ¬Έν©λλ€.
λ 볡μ‘ν νμ μλ리μ€μ κ²½μ° `Visitor` ν¨ν΄μ μ¬μ©ν μ μμ΅λλ€. λ°©λ¬Έμλ νΉμ λ Έλ μ νμ λν΄ νΈμΆλ λ©μλλ₯Ό μ μνλ κ°μ²΄μ λλ€. μ΄λ₯Ό ν΅ν΄ νμ νλ‘μΈμ€λ₯Ό μ¬μ©μ μ μνκ³ λ Έλ μ νμ λ°λΌ μμ μ μνν μ μμ΅λλ€.
import * as ts from "typescript";
import * as fs from "fs";
const fileName = "example.ts";
const sourceCode = fs.readFileSync(fileName, "utf8");
const sourceFile = ts.createSourceFile(
fileName,
sourceCode,
ts.ScriptTarget.ES2015,
true
);
class IdentifierVisitor {
visit(node: ts.Node) {
if (ts.isIdentifier(node)) {
console.log(`Found identifier: ${node.text}`);
}
ts.forEachChild(node, n => this.visit(n));
}
}
const visitor = new IdentifierVisitor();
visitor.visit(sourceFile);
μ€λͺ :
- IdentifierVisitor ν΄λμ€: `visit` λ©μλκ° μλ `IdentifierVisitor` ν΄λμ€λ₯Ό μ μν©λλ€.
- Visit λ©μλ: `visit` λ©μλλ νμ¬ λ Έλκ° `Identifier`μΈμ§ νμΈν©λλ€. κ·Έλ λ€λ©΄ μλ³μμ ν μ€νΈλ₯Ό μΆλ ₯ν©λλ€. κ·Έλ° λ€μ `ts.forEachChild`λ₯Ό μ¬κ·μ μΌλ‘ νΈμΆνμ¬ μμ λ Έλλ₯Ό λ°©λ¬Έν©λλ€.
- λ°©λ¬Έμ λ§λ€κΈ°: `IdentifierVisitor`μ μΈμ€ν΄μ€λ₯Ό λ§λλλ€.
- νμ μμ: `SourceFile`μμ `visit` λ©μλλ₯Ό νΈμΆνμ¬ νμμ μμν©λλ€.
μ΄ μμ μμλ ASTμμ λͺ¨λ μλ³μλ₯Ό μ°Ύλ λ°©λ²μ 보μ¬μ€λλ€. μ΄ ν¨ν΄μ μ μ©νμ¬ λ€λ₯Έ λ Έλ μ νμ μ°Ύκ³ λ€λ₯Έ μμ μ μνν μ μμ΅λλ€.
AST λ³ν
μ»΄νμΌλ¬ APIμ μ€μ μ±λ₯μ ASTλ₯Ό λ³ννλ κΈ°λ₯μ μμ΅λλ€. ASTλ₯Ό μμ νμ¬ μ½λμ ꡬ쑰μ λμμ λ³κ²½ν μ μμ΅λλ€. μ΄λ μ½λ 리ν©ν°λ§ λꡬ, μ½λ μμ±κΈ° λ° κΈ°ν κ³ κΈ ν΄λ§μ κΈ°μ΄μ λλ€.
ASTλ₯Ό λ³ννλ €λ©΄ `ts.transform` ν¨μλ₯Ό μ¬μ©ν΄μΌ ν©λλ€. μ΄ ν¨μλ `SourceFile`κ³Ό `TransformerFactory` ν¨μ λͺ©λ‘μ μ¬μ©ν©λλ€. `TransformerFactory`λ `TransformationContext`λ₯Ό κ°μ Έμ `Transformer` ν¨μλ₯Ό λ°ννλ ν¨μμ λλ€. `Transformer` ν¨μλ ASTμμ λ Έλλ₯Ό λ°©λ¬Ένκ³ λ³ννλ μν μ ν©λλ€.
λ€μμ TypeScript νμΌμ μμ λΆλΆμ μ£Όμμ μΆκ°νλ λ°©λ²μ 보μ¬μ£Όλ κ°λ¨ν μμ λλ€.
import * as ts from "typescript";
import * as fs from "fs";
const fileName = "example.ts";
const sourceCode = fs.readFileSync(fileName, "utf8");
const sourceFile = ts.createSourceFile(
fileName,
sourceCode,
ts.ScriptTarget.ES2015,
true
);
const transformerFactory: ts.TransformerFactory = context => {
return transformer => {
return node => {
if (ts.isSourceFile(node)) {
// Create a leading comment
const comment = ts.addSyntheticLeadingComment(
node,
ts.SyntaxKind.MultiLineCommentTrivia,
" This file was automatically transformed ",
true // hasTrailingNewLine
);
return node;
}
return node;
};
};
};
const { transformed } = ts.transform(sourceFile, [transformerFactory]);
const printer = ts.createPrinter({
newLine: ts.NewLineKind.LineFeed
});
const result = printer.printFile(transformed[0]);
fs.writeFileSync("example.transformed.ts", result);
μ€λͺ :
- TransformerFactory: `Transformer` ν¨μλ₯Ό λ°ννλ `TransformerFactory` ν¨μλ₯Ό μ μν©λλ€.
- Transformer: `Transformer` ν¨μλ νμ¬ λ Έλκ° `SourceFile`μΈμ§ νμΈν©λλ€. κ·Έλ λ€λ©΄ `ts.addSyntheticLeadingComment`λ₯Ό μ¬μ©νμ¬ λ Έλμ μ ν μ£Όμμ μΆκ°ν©λλ€.
- ts.transform: `ts.transform`μ νΈμΆνμ¬ `SourceFile`μ λ³νμ μ μ©ν©λλ€.
- νλ¦°ν°: λ³νλ ASTμμ μ½λλ₯Ό μμ±νκΈ° μν΄ `Printer` κ°μ²΄λ₯Ό λ§λλλ€.
- μΈμ λ° μ°κΈ°: λ³νλ μ½λλ₯Ό μΈμνκ³ `example.transformed.ts`λΌλ μ νμΌμ μλλ€.
μ΄ μμ μμλ κ°λ¨ν λ³νμ λ³΄μ¬ μ£Όμ§λ§ λμΌν ν¨ν΄μ μ¬μ©νμ¬ μ½λ 리ν©ν°λ§, λ‘κΉ λ¬Έ μΆκ° λλ μ€λͺ μ μμ±κ³Ό κ°μ λ 볡μ‘ν λ³νμ μνν μ μμ΅λλ€.
κ³ κΈ λ³ν κΈ°μ
μ»΄νμΌλ¬ APIμ ν¨κ» μ¬μ©ν μ μλ λͺ κ°μ§ κ³ κΈ λ³ν κΈ°μ μ λ€μκ³Ό κ°μ΅λλ€.
- μ λ Έλ λ§λ€κΈ°: `ts.createXXX` ν¨μλ₯Ό μ¬μ©νμ¬ μ AST λ Έλλ₯Ό λ§λλλ€. μλ₯Ό λ€μ΄ `ts.createVariableDeclaration`μ μ λ³μ μ μΈ λ Έλλ₯Ό λ§λλλ€.
- λ Έλ λ°κΎΈκΈ°: `ts.visitEachChild` ν¨μλ₯Ό μ¬μ©νμ¬ κΈ°μ‘΄ λ Έλλ₯Ό μ λ Έλλ‘ λ°κΏλλ€.
- λ Έλ μΆκ°: `ts.updateXXX` ν¨μλ₯Ό μ¬μ©νμ¬ ASTμ μ λ Έλλ₯Ό μΆκ°ν©λλ€. μλ₯Ό λ€μ΄ `ts.updateBlock`μ μ λ¬ΈμΌλ‘ λΈλ‘ λ¬Έμ μ λ°μ΄νΈν©λλ€.
- λ Έλ μ κ±°: λ³νκΈ° ν¨μμμ `undefined`λ₯Ό λ°ννμ¬ ASTμμ λ Έλλ₯Ό μ κ±°ν©λλ€.
μ½λ μμ±
ASTλ₯Ό λ³νν νμλ ASTμμ μ½λλ₯Ό μμ±ν΄μΌ ν©λλ€. μ»΄νμΌλ¬ APIλ μ΄λ₯Ό μν΄ `Printer` κ°μ²΄λ₯Ό μ 곡ν©λλ€. `Printer`λ ASTλ₯Ό κ°μ Έμ μ½λμ λ¬Έμμ΄ ννμ μμ±ν©λλ€.
`ts.createPrinter` ν¨μλ `Printer` κ°μ²΄λ₯Ό λ§λλλ€. μ¬μ©ν μ€ λ°κΏ λ¬Έμ λ° μ£Όμμ λ΄λ³΄λΌμ§ μ¬λΆμ κ°μ λ€μν μ΅μ μΌλ‘ νλ¦°ν°λ₯Ό ꡬμ±ν μ μμ΅λλ€.
`printer.printFile` λ©μλλ `SourceFile`μ κ°μ Έμ μ½λμ λ¬Έμμ΄ ννμ λ°νν©λλ€. κ·Έλ° λ€μ μ΄ λ¬Έμμ΄μ νμΌμ μΈ μ μμ΅λλ€.
μ»΄νμΌλ¬ APIμ μ€μ μμ© νλ‘κ·Έλ¨
TypeScript μ»΄νμΌλ¬ APIλ μννΈμ¨μ΄ κ°λ°μμ μλ§μ μ€μ μμ© νλ‘κ·Έλ¨μ κ°μ§κ³ μμ΅λλ€. λ€μμ λͺ κ°μ§ μμ λλ€.
- λ¦°ν°: μ½λ© νμ€μ μ μ©νκ³ μ½λμμ μ μ¬μ μΈ λ¬Έμ λ₯Ό μλ³νκΈ° μν΄ μ¬μ©μ μ§μ λ¦°ν°λ₯Ό λΉλν©λλ€.
- μ½λ ν¬λ§·ν°: νΉμ μ€νμΌ κ°μ΄λμ λ°λΌ μ½λλ₯Ό μλμΌλ‘ ν¬λ§·νλ μ½λ ν¬λ§·ν°λ₯Ό λ§λλλ€.
- μ μ λΆμκΈ°: μ½λμμ λ²κ·Έ, 보μ μ·¨μ½μ λ° μ±λ₯ λ³λͺ© νμμ κ°μ§νκΈ° μν΄ μ μ λΆμκΈ°λ₯Ό κ°λ°ν©λλ€.
- μ½λ μμ±κΈ°: ν νλ¦Ώ λλ κΈ°ν μ λ ₯μμ μ½λλ₯Ό μμ±νμ¬ λ°λ³΅μ μΈ μμ μ μλννκ³ μμ©κ΅¬ μ½λλ₯Ό μ€μ λλ€. μλ₯Ό λ€μ΄ μ€λͺ νμΌμμ API ν΄λΌμ΄μΈνΈ λλ λ°μ΄ν°λ² μ΄μ€ μ€ν€λ§λ₯Ό μμ±ν©λλ€.
- 리ν©ν°λ§ λꡬ: λ³μ μ΄λ¦μ μλμΌλ‘ λ°κΎΈκ±°λ ν¨μλ₯Ό μΆμΆνκ±°λ νμΌ κ°μ μ½λλ₯Ό μ΄λνλ 리ν©ν°λ§ λꡬλ₯Ό λΉλν©λλ€.
- κ΅μ ν(i18n) μλν: TypeScript μ½λμμ λ²μ κ°λ₯ν λ¬Έμμ΄μ μλμΌλ‘ μΆμΆνκ³ λ€λ₯Έ μΈμ΄μ λν μ§μν νμΌμ μμ±ν©λλ€. μλ₯Ό λ€μ΄ λκ΅¬κ° `translate()` ν¨μμ μ λ¬λ λ¬Έμμ΄μ λν΄ μ½λλ₯Ό κ²μνκ³ λ²μ 리μμ€ νμΌμ μλμΌλ‘ μΆκ°ν μ μμ΅λλ€.
μ: κ°λ¨ν λ¦°ν° λΉλ
TypeScript μ½λμμ μ¬μ©λμ§ μμ λ³μλ₯Ό νμΈνλ κ°λ¨ν λ¦°ν°λ₯Ό λ§λ€μ΄ λ³΄κ² μ΅λλ€. μ΄ λ¦°ν°λ μ μΈλμμ§λ§ μ¬μ©λμ§ μμ λ³μλ₯Ό μλ³ν©λλ€.
import * as ts from "typescript";
import * as fs from "fs";
const fileName = "example.ts";
const sourceCode = fs.readFileSync(fileName, "utf8");
const sourceFile = ts.createSourceFile(
fileName,
sourceCode,
ts.ScriptTarget.ES2015,
true
);
function findUnusedVariables(sourceFile: ts.SourceFile) {
const usedVariables = new Set();
function visit(node: ts.Node) {
if (ts.isIdentifier(node)) {
usedVariables.add(node.text);
}
ts.forEachChild(node, visit);
}
visit(sourceFile);
const unusedVariables: string[] = [];
function checkVariableDeclaration(node: ts.Node) {
if (ts.isVariableDeclaration(node) && node.name && ts.isIdentifier(node.name)) {
const variableName = node.name.text;
if (!usedVariables.has(variableName)) {
unusedVariables.push(variableName);
}
}
ts.forEachChild(node, checkVariableDeclaration);
}
checkVariableDeclaration(sourceFile);
return unusedVariables;
}
const unusedVariables = findUnusedVariables(sourceFile);
if (unusedVariables.length > 0) {
console.log("Unused variables:");
unusedVariables.forEach(variable => console.log(`- ${variable}`));
} else {
console.log("No unused variables found.");
}
μ€λͺ :
- findUnusedVariables ν¨μ: `SourceFile`μ μ λ ₯μΌλ‘ μ¬μ©νλ `findUnusedVariables` ν¨μλ₯Ό μ μν©λλ€.
- usedVariables μ§ν©: μ¬μ©λ λ³μμ μ΄λ¦μ μ μ₯νκΈ° μν΄ `Set`μ λ§λλλ€.
- visit ν¨μ: ASTλ₯Ό νμνκ³ λͺ¨λ μλ³μμ μ΄λ¦μ `usedVariables` μ§ν©μ μΆκ°νλ μ¬κ· ν¨μ `visit`λ₯Ό μ μν©λλ€.
- checkVariableDeclaration ν¨μ: λ³μ μ μΈμ΄ μ¬μ©λμ§ μμλμ§ νμΈνλ μ¬κ· ν¨μ `checkVariableDeclaration`μ μ μν©λλ€. κ·Έλ λ€λ©΄ λ³μ μ΄λ¦μ `unusedVariables` λ°°μ΄μ μΆκ°ν©λλ€.
- unusedVariables λ°ν: μ¬μ©λμ§ μμ λ³μμ μ΄λ¦μ΄ ν¬ν¨λ λ°°μ΄μ λ°νν©λλ€.
- μΆλ ₯: μ¬μ©λμ§ μμ λ³μλ₯Ό μ½μμ μΆλ ₯ν©λλ€.
μ΄ μμ μμλ κ°λ¨ν λ¦°ν°λ₯Ό 보μ¬μ€λλ€. μ΄λ₯Ό νμ₯νμ¬ λ€λ₯Έ μ½λ© νμ€μ νμΈνκ³ μ½λμμ λ€λ₯Έ μ μ¬μ μΈ λ¬Έμ λ₯Ό μλ³ν μ μμ΅λλ€. μλ₯Ό λ€μ΄ μ¬μ©λμ§ μμ κ°μ Έμ€κΈ°, μ§λμΉκ² 볡μ‘ν ν¨μ λλ μ μ¬μ μΈ λ³΄μ μ·¨μ½μ μ νμΈν μ μμ΅λλ€. ν΅μ¬μ ASTλ₯Ό νμνκ³ κ΄μ¬ μλ νΉμ λ Έλ μ νμ μλ³νλ λ°©λ²μ μ΄ν΄νλ κ²μ λλ€.
λͺ¨λ² μ¬λ‘ λ° κ³ λ € μ¬ν
- AST μ΄ν΄: AST ꡬ쑰λ₯Ό μ΄ν΄νλ λ° μκ°μ ν¬μν©λλ€. AST νμκΈ°μ κ°μ λꡬλ₯Ό μ¬μ©νμ¬ μ½λμ ASTλ₯Ό μκ°νν©λλ€.
- μ ν κ°λ μ¬μ©: μ ν κ°λ(`ts.isXXX`)λ₯Ό μ¬μ©νμ¬ μ¬λ°λ₯Έ λ Έλ μ νμΌλ‘ μμ νκ³ μλμ§ νμΈν©λλ€.
- μ±λ₯ κ³ λ €: AST λ³νμ κ³μ° λΉμ©μ΄ λ§μ΄ λ€ μ μμ΅λλ€. μ½λλ₯Ό μ΅μ ννμ¬ λ°©λ¬Ένκ³ λ³ννλ λ Έλ μλ₯Ό μ΅μνν©λλ€.
- μ€λ₯ μ²λ¦¬: μ€λ₯λ₯Ό μ μμ μΌλ‘ μ²λ¦¬ν©λλ€. ASTμμ μ ν¨νμ§ μμ μμ μ μννλ €κ³ νλ©΄ μ»΄νμΌλ¬ APIμμ μμΈλ₯Ό throwν μ μμ΅λλ€.
- μ² μ ν ν μ€νΈ: λ³νμ΄ μνλ κ²°κ³Όλ₯Ό μμ±νκ³ μλ‘μ΄ λ²κ·Έλ₯Ό λ°μμν€μ§ μλλ‘ λ³νμ μ² μ ν ν μ€νΈν©λλ€.
- κΈ°μ‘΄ λΌμ΄λΈλ¬λ¦¬ μ¬μ©: μ»΄νμΌλ¬ APIμ λν λ λμ μμ€μ μΆμνλ₯Ό μ 곡νλ κΈ°μ‘΄ λΌμ΄λΈλ¬λ¦¬λ₯Ό μ¬μ©νλ κ²μ΄ μ’μ΅λλ€. μ΄λ¬ν λΌμ΄λΈλ¬λ¦¬λ μΌλ°μ μΈ μμ μ λ¨μννκ³ μμ±ν΄μΌ νλ μ½λ μμ μ€μΌ μ μμ΅λλ€. μλ‘λ `ts-morph` λ° `typescript-eslint`κ° μμ΅λλ€.
κ²°λ‘
TypeScript μ»΄νμΌλ¬ APIλ κ³ κΈ κ°λ° λꡬλ₯Ό ꡬμΆνκΈ° μν κ°λ ₯ν λꡬμ λλ€. ASTλ₯Ό μ¬μ©νμ¬ μμ νλ λ°©λ²μ μ΄ν΄νλ©΄ μ½λ νμ§μ κ°μ νκ³ λ°λ³΅μ μΈ μμ μ μλννλ©° κ°λ°μ μμ°μ±μ ν₯μμν€λ λ¦°ν°, μ½λ ν¬λ§·ν°, μ μ λΆμκΈ° λ° κΈ°ν λꡬλ₯Ό λ§λ€ μ μμ΅λλ€. APIκ° λ³΅μ‘ν μ μμ§λ§ μ΄λ₯Ό λ§μ€ν°νλ©΄ μ»μ μ μλ μ΄μ μ μλΉν©λλ€. μ΄ μ’ ν© κ°μ΄λλ νλ‘μ νΈμμ μ»΄νμΌλ¬ APIλ₯Ό ν¨κ³Όμ μΌλ‘ νμνκ³ νμ©νκΈ° μν ν λλ₯Ό μ 곡ν©λλ€. AST Explorerμ κ°μ λꡬλ₯Ό νμ©νκ³ λ Έλ μ νμ μ μ€νκ² μ²λ¦¬νλ©° λ³νμ μ² μ ν ν μ€νΈνλ κ²μ μμ§ λ§μμμ€. μ°μ΅κ³Ό νμ μ ν΅ν΄ TypeScript μ»΄νμΌλ¬ APIμ λͺ¨λ μ μ¬λ ₯μ μ κΈ ν΄μ νκ³ μννΈμ¨μ΄ κ°λ° νκ²½μ μν νμ μ μΈ μ루μ μ ꡬμΆν μ μμ΅λλ€.
μΆκ° νμ:
- TypeScript μ»΄νμΌλ¬ API λ¬Έμ: [https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API](https://github.com/microsoft/TypeScript/wiki/Using-the-Compiler-API)
- AST νμκΈ°: [https://astexplorer.net/](https://astexplorer.net/)
- ts-morph λΌμ΄λΈλ¬λ¦¬: [https://ts-morph.com/](https://ts-morph.com/)
- typescript-eslint: [https://typescript-eslint.io/](https://typescript-eslint.io/)