What Is an Expression Tree?
An expression tree is a binary data structure used to represent and evaluate mathematical and logical operations.
An expression tree has two main characteristics:
1.- It is a binary tree
It is a structure composed of nodes (elements or pieces of data). Unlike a linear structure, a tree is organized hierarchically, which means each node is positioned above or below another.
From each node, up to two child nodes can branch out.
If you want to learn more about binary trees, visit the post “Binary Tree: What It Is, Uses, Types, and How to Create One with JavaScript/TypeScript.”

2.- It evaluates mathematical and logical operations
Expression trees are mainly used in:
- Calculators
- Spreadsheets (such as Excel)
- Compilers
- Programming languages
They allow operations such as addition, subtraction, multiplication, and division to be represented in a structured way.
How Is an Expression Tree Formed?
A tree is made up of two main types of nodes:
- Leaf nodes: These are the nodes found at the ends of the tree. They have no children and usually represent numeric values.
- Internal nodes: These nodes have at least one child. In an expression tree, they represent mathematical operators such as +, -, *, or /.

How Do You Evaluate an Expression Tree?
Expression trees are evaluated from the bottom up. This happens because the tree structure respects operator precedence:
- The deepest operators are executed first
- The root node operation is executed last
Simple example:
Let’s solve the expression: (2 + 1) * 3
First, we solve the deepest operation:
2 + 1 = 3
This result becomes a node that is then multiplied by 3.
Finally:
3 * 3 = 9

This is how an expression tree allows us to evaluate operations in the correct order.
👉 In summary: An expression tree is solved from the bottom up, evaluating the most internal operations first until reaching the final result.
How to Create an Expression Tree with Code?
To create an expression tree, we can use a class that represents a tree node.
class BinaryTree {
value: number | "add" | "subtract" | "multiply"
left: BinaryTree | null
right: BinaryTree | null
constructor(value: number | "add" | "subtract" | "multiply") {
this.value = value
this.left = null
this.right = null
}
}
This class contains three properties:
- value: can be a number or an operator
- left: reference to the left child
- right: reference to the right child
To better understand how to create a binary tree from scratch, you can visit the article mentioned earlier.
How Do We Solve an Expression Tree Recursively?
First, let’s understand what a recursive function is and why recursion is natural for trees.
A recursive function is one that calls itself until it reaches a base case that stops execution.
For example, imagine we want to count from 3 down to 0 and print each number to the console. Our base case is reaching 0; once that happens, the function stops. The function receives a number and subtracts 1 on each call. With recursion, the function keeps calling itself until it reaches that base case.
const count = (number: number): void => {
if (number === 0) return; // base case (stops the function)
console.log(number)
count(number - 1); // the function calls itself
};
count(3);
Recursion is especially useful when working with trees because each node in a tree can be seen as a smaller tree.
Think of a real tree 🌳. If you look at a large branch, you’ll notice it resembles the entire tree—it also has smaller branches that continue dividing.
The same happens in a data tree. Each node has:
- a value
- a left subtree
- a right subtree
Solving the entire tree is simply repeating the same process on each of its subtrees.

Now we are ready to solve our expression tree.
Step 1 — Create the Function with TypeScript
The function receives a node and must return a number.
const evaluateExpressionTree = (node: BinaryTree | null): number => {}
Step 2 — Define the Base Cases
We want to stop recursion when:
✅ The node is null. Here we return 0 for simplicity, but using throw new Error may be a better practice.
✅ The node contains a number (it is a leaf node). In that case, we return the value so it can be used in the mathematical operation.
const evaluateExpressionTree = (node: BinaryTree | null): number => {
if (!node) return 0
if (typeof node.value === "number") {
return node.value
}
}
Step 3 — Evaluate the Subtrees
Now we evaluate the children:
const leftValue = evaluateExpressionTree(node.left)
const rightValue = evaluateExpressionTree(node.right)
The leftValue and rightValue are the result of recursively calling evaluateExpressionTree.
Step 4 — Apply the Operation
We use a switch statement that adds, subtracts, or multiplies depending on the node’s value.
const evaluateExpressionTree = (node: BinaryTree | null): number => {
if (!node) return 0
if (typeof node.value === "number") {
return node.value
}
const leftValue = evaluateExpressionTree(node.left)
const rightValue = evaluateExpressionTree(node.right)
switch (node.value) {
case "add":
return leftValue + rightValue
case "subtract":
return leftValue - rightValue
case "multiply":
return leftValue * rightValue
}
return 0
}
Now we have a function capable of evaluating an entire tree.
I recommend grabbing a piece of paper and a pencil and trying to solve a simple tree by following the function step by step.