CodeBlanks Logo Icon CodeBlanks

Challenge 2: Transformer

Solve a task requiring your own transformer.

Code transformation with a transformer

In this challenge you will write your own transformer. Produce new nodes with ts.factory, transform children with ts.visitEachChild, and apply with ts.transform. You will replace specific node kinds (TrueKeyword, NumericLiteral).

Practice Replace true with false

Create a SourceFile from let a = true; let b = true;. Write a transformer that replaces TrueKeyword nodes with ts.factory.createFalse(). Descend with ts.visitEachChild. Apply with ts.transform and print with ts.createPrinter.

Starter code

index.ts
import * as ts from "typescript";

// Kaynak: let a = true; let b = true;
// SourceFile oluştur
// Bir transformer yaz: TrueKeyword düğümlerini FalseKeyword ile değiştir
// False düğümü üretmek için factory kullan
// transform ile uygula
// Printer ile sonucu yazdır

// kodunu buraya yaz

Sample solution

index.ts
import ts from "typescript";

const sourceText = "let a = true; let b = true;";
const sf = ts.createSourceFile("app.ts", sourceText, ts.ScriptTarget.Latest, true);

const transformer: ts.TransformerFactory<ts.SourceFile> = function(context: ts.TransformationContext) {
  return function visit(node: ts.Node): ts.Node {
    if (node.kind === ts.SyntaxKind.TrueKeyword) {
      return ts.factory.createFalse();
    }
    return ts.visitEachChild(node, visit, context);
  };
};

const result = ts.transform(sf, [transformer]);
const printer = ts.createPrinter();
process.stdout.write(printer.printFile(result.transformed[0] as ts.SourceFile));
result.dispose();

Expected output

let a = false;
let b = false;

Practice Replace numbers with 0

Create a SourceFile from let a = 5; let b = 10; let c = 15;. Write a transformer that replaces NumericLiteral nodes with ts.factory.createNumericLiteral("0"). Descend with ts.visitEachChild. Apply with ts.transform and print with ts.createPrinter.

Starter code

index.ts
import * as ts from "typescript";

// Kaynak: let a = 5; let b = 10; let c = 15;
// SourceFile oluştur
// Bir transformer yaz: NumericLiteral düğümlerini 0 ile değiştir
// Sayısal düğüm üretmek için factory kullan
// transform ile uygula
// Printer ile sonucu yazdır

// kodunu buraya yaz

Sample solution

index.ts
import ts from "typescript";

const sourceText = "let a = 5; let b = 10; let c = 15;";
const sf = ts.createSourceFile("app.ts", sourceText, ts.ScriptTarget.Latest, true);

const transformer: ts.TransformerFactory<ts.SourceFile> = function(context: ts.TransformationContext) {
  return function visit(node: ts.Node): ts.Node {
    if (ts.isNumericLiteral(node)) {
      return ts.factory.createNumericLiteral("0");
    }
    return ts.visitEachChild(node, visit, context);
  };
};

const result = ts.transform(sf, [transformer]);
const printer = ts.createPrinter();
process.stdout.write(printer.printFile(result.transformed[0] as ts.SourceFile));
result.dispose();

Expected output

let a = 0;
let b = 0;
let c = 0;

Questions and answers

Review the lesson questions together with their answers. To test yourself, solve the lesson interactively.

1 Which method is used to transform child nodes in a transformer?

  • ts.forEachChild
  • ts.mapChildren
  • ts.transformChildren
  • ts.visitEachChild Correct answer

Explanation: ts.visitEachChild transforms child nodes with a visitor and returns a new parent; forEachChild is read-only, and transformChildren and mapChildren do not exist.

2 Create a false node

Question
if (node.kind === ts.SyntaxKind.TrueKeyword) {
  return ts.factory.____();
}
Answer
if (node.kind === ts.SyntaxKind.TrueKeyword) {
  return ts.factory.createFalse();
}

Explanation: ts.factory.createFalse produces a BooleanLiteral (FalseKeyword) node; createBoolean and createFalseKeyword do not exist on the factory, and createLiteral is a different API.

3 Transformer parts

Term Meaning
ts.transform Applies the transformer
ts.factory Produces nodes
ts.visitEachChild Transforms children
ts.SyntaxKind Gives the node kind

All lessons in Expert