TypeScript
AST model
Design a mini AST model with discriminated unions.
AST model
An AST (Abstract Syntax Tree) is a tree representing a program's structure. With discriminated unions each node type is modeled with a kind discriminant field; each type carries its own fields. This provides type-safe branching when writing a compiler.
type Node =
| { kind: "number"; value: number }
| { kind: "string"; value: string }
| { kind: "add"; left: Node; right: Node };
Branching with discriminant
The kind discriminant field enables branching via switch statement. Each case narrows to the relevant node's own fields; for example in the case "number" branch node.value is accessed as number. This prevents wrong access at compile time.
function label(n: Node): string {
switch (n.kind) {
case "number": return "number: " + n.value;
case "string": return "string: " + n.value;
case "add": return "add";
}
}
Exercise Define the AST Node type
Define the Node discriminated union type: "number" (value: number), "string" (value: string), "add" (left: Node, right: Node) members, with a kind discriminant field. Write a kindOf(n: Node): string function using switch: for number return "n", for string return "s", for add return "a". Print the result via console.log(kindOf({ kind: "number", value: 42 })).
Show example solution
type Node =
| { kind: "number"; value: number }
| { kind: "string"; value: string }
| { kind: "add"; left: Node; right: Node };
function kindOf(n: Node): string {
switch (n.kind) {
case "number":
return "n";
case "string":
return "s";
case "add":
return "a";
}
}
console.log(kindOf({ kind: "number", value: 42 }));
Test yourself
-
What is the advantage of modeling AST nodes with a discriminated union?
- It increases runtime speed
- It reduces the number of nodes
- It makes the code shorter
- It provides type-safe branching
Show answer
It provides type-safe branching — A discriminated union allows safe narrowing via switch on each node's kind field; wrong access is caught at compile time.
-
AST node discriminant
type Node =
| { kind: "number"; value: number }
| { kind: ____; value: string }
| { kind: "add"; left: Node; right: Node };
Show answer
type Node =
| { kind: "number"; value: number }
| { kind: "string"; value: string }
| { kind: "add"; left: Node; right: Node };
-
AST model parts
- kind discriminant
- indicates node type
- Node union
- combines all node types
- discriminated union
- type-safe branching
- value, left, right
- node-specific fields
Next lesson: Visitor design