CodeBlanks Logo Icon CodeBlanks

Diagnostic production

Learn to produce your own diagnostics.

Position information

When a rule violation is found, you report it with position info. node.getStart(sourceFile) gives the node's start offset; ts.getLineAndCharacterOfPosition(sf, offset) returns a { line, character } object. line is 0-indexed.

const start = node.getStart(sf);
const { line } = ts.getLineAndCharacterOfPosition(sf, start);
console.log(`line ${line + 1}: error`);

Collecting errors

To collect errors at once you use an array. On each violation you push text with errors.push(...), and at the end you print with errors.join("\n"). This pattern mirrors TypeScript's own diagnostics mechanism.

const errors: string[] = [];
// on violation:
errors.push(`line ${line + 1}: message`);
console.log(errors.join("\n"));

Practice Report any types

Create a source with three variables, each on its own line: let a: any = 1;, let b: number = 2; and let c: any = 3;. Write a visit function that finds VariableDeclaration nodes whose type annotation is any and collects an error with its line number into a list. Walk with ts.forEachChild and print one error per line.

Starter code

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

// Üç satırlık kaynak: let a: any = 1; / let b: number = 2; / let c: any = 3;
// SourceFile oluştur
// visit fonksiyonu yaz: any türü olan VariableDeclaration bul
// Satır numarasıyla hatayı topla
// forEachChild ile gez
// Hataları her satırda bir tane olarak yazdır

// kodunu buraya yaz

Sample solution

index.ts
import ts from "typescript";

const sourceText = 'let a: any = 1;\nlet b: number = 2;\nlet c: any = 3;';
const sf = ts.createSourceFile("app.ts", sourceText, ts.ScriptTarget.Latest, true);

const errors: string[] = [];
function visit(node: ts.Node) {
  if (ts.isVariableDeclaration(node) && node.type?.kind === ts.SyntaxKind.AnyKeyword) {
    const { line } = ts.getLineAndCharacterOfPosition(sf, node.getStart(sf));
    errors.push(`line ${line + 1}: any`);
  }
  ts.forEachChild(node, visit);
}
visit(sf);
console.log(errors.join("\n"));

Expected output

line 1: any
line 3: any

Questions and answers

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

1 What does ts.getLineAndCharacterOfPosition(sf, offset) return?

  • A { line, character } object Correct answer
  • Only the line number
  • An offset number
  • A Type object

Explanation: getLineAndCharacterOfPosition returns a { line, character } object where line is 0-indexed. It does not return a Type, a single line number or an offset.

2 Get the line number

Question
const start = node.getStart(sf);
const pos = ts.____(sf, start);
console.log(pos.line + 1);
Answer
const start = node.getStart(sf);
const pos = ts.getLineAndCharacterOfPosition(sf, start);
console.log(pos.line + 1);

Explanation: ts.getLineAndCharacterOfPosition returns a { line, character } object; getLineOfPosition, getPosition and getLineNumber do not exist.

3 Error reporting parts

Term Meaning
node.getStart(sf) Gives the start offset
getLineAndCharacterOfPosition Gives line and character
errors.push Adds the error to the list
errors.join Turns the list into text

All lessons in Expert